All of lore.kernel.org
 help / color / mirror / Atom feed
From: ebiederm@xmission.com (Eric W. Biederman)
To: "H. Peter Anvin" <hpa@zytor.com>
Cc: hacklu <embedway.linux@gmail.com>, linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] x86, boot: Optimize the elf header handling.
Date: Sun, 03 Jun 2012 13:32:59 -0700	[thread overview]
Message-ID: <877gvob0g4.fsf_-_@xmission.com> (raw)
In-Reply-To: <87fwacb0jq.fsf_-_@xmission.com> (Eric W. Biederman's message of "Sun, 03 Jun 2012 13:30:49 -0700")


Create a space for the elf headers at the begginng of the
kernels image in memory.  Removing the need for an extra
copy of the kernel during boot.  Making things faster
and making vmlinux smaller.

- Allow room for the elf headers in the vmlinux.
  This removes the need to insert padding between
  the elf headers and the start of text.  Reducing
  the size of vmlinux by 2MB on x86_64 and removing
  the need for parse_elf in boot.c to move the code.

- Return the relocated entry point address from parse_elf
  as the kernel's entry point is no long at a fixed address.

- Remove the now unnecessary copies in arch/x86/compress/misc.c:parse_elf
  The ELF headers are now guaranteed to not conflict with the program
  data in the uncompressed image.

- In cleanup_highmap keep all pages starting with __START_KERNEL_map
  instead of _text.  Those values used to be the same but with the
  insertion of the hole for the ELF headers they differ and cause us
  to nuke our first 2MB of text ouch!  So use the __START_KERNEL_map
  which includes the elf headers.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 arch/x86/boot/compressed/head_32.S |    2 +-
 arch/x86/boot/compressed/head_64.S |    2 +-
 arch/x86/boot/compressed/misc.c    |   60 +++++++++++------------------------
 arch/x86/kernel/vmlinux.lds.S      |    4 +-
 arch/x86/mm/init_64.c              |    3 +-
 5 files changed, 25 insertions(+), 46 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index c85e3ac..1b15e2c 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -211,7 +211,7 @@ relocated:
  * Jump to the decompressed kernel.
  */
 	xorl	%ebx, %ebx
-	jmp	*%ebp
+	jmp	*%eax
 
 /*
  * Stack and heap for uncompression
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 87e03a1..9b8d782 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -337,7 +337,7 @@ relocated:
 /*
  * Jump to the decompressed kernel.
  */
-	jmp	*%rbp
+	jmp	*%rax
 
 	.data
 gdt:
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 5b04b66..fc34e8a 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -198,23 +198,23 @@ static void error(char *x)
 		asm("hlt");
 }
 
-static void parse_elf(void *output)
+static void *parse_elf(void *output)
 {
 #ifdef CONFIG_X86_64
-	Elf64_Ehdr ehdr;
-	Elf64_Phdr *phdrs, *phdr;
+	Elf64_Ehdr *ehdr;
+	Elf64_Phdr *phdrs;
 #else
-	Elf32_Ehdr ehdr;
-	Elf32_Phdr *phdrs, *phdr;
+	Elf32_Ehdr *ehdr;
+	Elf32_Phdr *phdrs;
 #endif
 	void *dest;
 	int i;
 
-	memcpy(&ehdr, output, sizeof(ehdr));
-	if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
-	   ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
-	   ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
-	   ehdr.e_ident[EI_MAG3] != ELFMAG3) {
+	ehdr = output;
+	if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
+	    ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
+	    ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
+	    ehdr->e_ident[EI_MAG3] != ELFMAG3) {
 		error("Kernel is not a valid ELF file");
 		return;
 	}
@@ -222,39 +222,17 @@ static void parse_elf(void *output)
 	if (!quiet)
 		putstr("Parsing ELF... ");
 
-	phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
-	if (!phdrs)
-		error("Failed to allocate space for phdrs");
+	phdrs = output + ehdr->e_phoff;
 
-	memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum);
-
-	for (i = 0; i < ehdr.e_phnum; i++) {
-		phdr = &phdrs[i];
-
-		switch (phdr->p_type) {
-		case PT_LOAD:
-#ifdef CONFIG_RELOCATABLE
-			dest = output;
-			dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
-#else
-			dest = (void *)(phdr->p_paddr);
-#endif
-			memcpy(dest,
-			       output + phdr->p_offset,
-			       phdr->p_filesz);
-			break;
-		default: /* Ignore other PT_* */ break;
-		}
-	}
-
-	free(phdrs);
+	return output + (ehdr->e_entry - LOAD_PHYSICAL_ADDR);
 }
 
-asmlinkage void decompress_kernel(void *rmode, memptr heap,
-				  unsigned char *input_data,
-				  unsigned long input_len,
-				  unsigned char *output)
+asmlinkage void *decompress_kernel(void *rmode, memptr heap,
+				   unsigned char *input_data,
+				   unsigned long input_len,
+				   unsigned char *output)
 {
+	void *entry;
 	real_mode = rmode;
 
 	if (cmdline_find_option_bool("quiet"))
@@ -297,8 +275,8 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 	if (!quiet)
 		putstr("\nDecompressing Linux... ");
 	decompress(input_data, input_len, NULL, NULL, output, NULL, error);
-	parse_elf(output);
+	entry = parse_elf(output);
 	if (!quiet)
 		putstr("done.\nBooting the kernel.\n");
-	return;
+	return entry;
 }
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 22a1530..af6fb8a 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -82,10 +82,10 @@ PHDRS {
 SECTIONS
 {
 #ifdef CONFIG_X86_32
-        . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
+        . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR + SIZEOF_HEADERS;
         phys_startup_32 = startup_32 - LOAD_OFFSET;
 #else
-        . = __START_KERNEL;
+        . = __START_KERNEL + SIZEOF_HEADERS;
         phys_startup_64 = startup_64 - LOAD_OFFSET;
 #endif
 
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 2b6b4a3..e8599cd 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -303,13 +303,14 @@ void __init cleanup_highmap(void)
 {
 	unsigned long vaddr = __START_KERNEL_map;
 	unsigned long vaddr_end = __START_KERNEL_map + (max_pfn_mapped << PAGE_SHIFT);
+	unsigned long text = __START_KERNEL_map;
 	unsigned long end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1;
 	pmd_t *pmd = level2_kernel_pgt;
 
 	for (; vaddr + PMD_SIZE - 1 < vaddr_end; pmd++, vaddr += PMD_SIZE) {
 		if (pmd_none(*pmd))
 			continue;
-		if (vaddr < (unsigned long) _text || vaddr > end)
+		if (vaddr < text || vaddr > end)
 			set_pmd(pmd, __pmd(0));
 	}
 }
-- 
1.7.5.4


  reply	other threads:[~2012-06-03 20:33 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-17  5:56 why the decompressed procedure move kernel from address 0x100000(1M) to 0x1000000(16M) +x hacklu
2012-06-02 23:48 ` Eric W. Biederman
2012-06-03  3:10   ` H. Peter Anvin
2012-06-03  8:41     ` Eric W. Biederman
2012-06-03 13:01       ` H. Peter Anvin
2012-06-03 20:30         ` [PATCH 1/2] x86, boot: Don't overlap the compressed and non-compressed image Eric W. Biederman
2012-06-03 20:32           ` Eric W. Biederman [this message]
2012-07-01 14:56             ` [tip:x86/boot] x86, boot: Optimize the elf header handling tip-bot for Eric W. Biederman
2012-07-01 15:04             ` [PATCH 2/2] " H. Peter Anvin
2012-07-01 15:34               ` H. Peter Anvin
2012-07-01 16:08                 ` Eric W. Biederman
2012-07-01 16:11                   ` H. Peter Anvin
2012-07-01 16:26                     ` Eric W. Biederman
2012-07-01 16:44                       ` H. Peter Anvin
2012-07-01 17:09                         ` Eric W. Biederman
2012-07-01 17:15                           ` H. Peter Anvin
2012-07-01 18:25                             ` Eric W. Biederman
2012-07-01 18:37                               ` H. Peter Anvin
2012-07-01 19:20                                 ` Eric W. Biederman
2012-07-01 19:23                                   ` H. Peter Anvin
2012-07-01 20:40                                     ` Eric W. Biederman
2012-07-01 20:52                                       ` H. Peter Anvin
2012-07-09  6:50                                         ` Eric W. Biederman
2012-07-09  6:52                                           ` [PATCH 1/4] x86 boot: Jump to the entry point address in the elf header Eric W. Biederman
2012-07-09  6:53                                             ` [PATCH 2/4] x86 boot: Optimize the elf header handling Eric W. Biederman
2012-07-09  6:55                                             ` [PATCH 3/4] x86 boot: When building vmlinux.bin properly precompute the memory image Eric W. Biederman
2012-07-09  6:56                                             ` [PATCH 4/4] x86 boot: Tell ld the kernel doesn't want 2MB file offset alignment Eric W. Biederman
2012-07-09  6:59                                             ` [PATCH 1/4] x86 boot: Jump to the entry point address in the elf header Eric W. Biederman
2012-07-02 16:56                                 ` [PATCH 2/2] x86, boot: Optimize the elf header handling Tejun Heo
2012-07-09  7:03                                   ` Eric W. Biederman
2012-07-01  2:23           ` [PATCH 1/2] x86, boot: Don't overlap the compressed and non-compressed image Eric W. Biederman
2012-07-01  2:32             ` H. Peter Anvin
2012-07-01  5:22               ` Eric W. Biederman
2012-07-01 14:55           ` [tip:x86/boot] x86, boot: Don' t " tip-bot for Eric W. Biederman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877gvob0g4.fsf_-_@xmission.com \
    --to=ebiederm@xmission.com \
    --cc=embedway.linux@gmail.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.