All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] x86/boot: make ELF kernel multiboot-able
@ 2017-02-15 14:41 Chao Peng
  2017-02-15 16:42 ` Paolo Bonzini
  2017-02-15 18:12 ` hpa
  0 siblings, 2 replies; 10+ messages in thread
From: Chao Peng @ 2017-02-15 14:41 UTC (permalink / raw)
  To: linux-kernel, x86, grub-devel
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Andy Lutomirski,
	Juergen Gross, Luis R. Rodriguez, Borislav Petkov,
	Josh Poimboeuf, Thomas Garnier, Al Viro, Michael S. Tsirkin,
	Paolo Bonzini, Amnon Ilan

Multiboot specification (http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.texi?h=multiboot2)
is an open standard that provides kernels with a uniform way to be booted
by multiboot-compliant bootloaders (like grub).

This patch is trying to make Linux ELF kernel image to be a
multiboot-compliant OS so that it can be loaded by a multiboot-comliant
bootloader. The benefit is eliminating the maintainance for realmode and
decompression code and especially when the kernel is loaded in a virtual
machine, the reducing for these code can greatly cuts down the boot time.

However, the current version of multiboot spec doesn't support 64 bit
well so for 64 bit kernel we need stub code to jump from 32 bit code to
64 bit code. Besides, there are still some other issues:
  1). '-z max-page-size=0x1000' is used so the text segment start is in
  multiboot header search scope because GNU LD has default page size of
  0x00200000 for ELF64, which will fail multiboot test.

  2). The bootloader like grub has support for ELF kernel (even for ELF64)
  which makes the patch easier. However, the current grub implementaion
  thinks the entry address should be a VA. E.g. for 64 bit kernel, the entry
  address (0x1000000) is actually phiscial address, grub refuses to load it
  by saying: 'entry point isn't in a segment'.

This patch is sent out as RFC in case you have some ideas.

Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
---
 arch/x86/Kconfig             |   6 +
 arch/x86/Makefile            |   4 +
 arch/x86/kernel/head64.c     |  64 ++++++-
 arch/x86/kernel/head_64.S    | 175 ++++++++++++++++++
 arch/x86/kernel/multiboot2.h | 417 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 665 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/kernel/multiboot2.h

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bada636..75a9ef2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -585,6 +585,12 @@ config X86_AMD_PLATFORM_DEVICE
 	  I2C and UART depend on COMMON_CLK to set clock. GPIO driver is
 	  implemented under PINCTRL subsystem.
 
+config X86_MULTIBOOT_STUB
+	bool "Multiboot stub support for ELF kernel image"
+	default n
+	---help---
+	  Set whether multiboot stub is on or off.
+
 config IOSF_MBI
 	tristate "Intel SoC IOSF Sideband support for SoC platforms"
 	depends on PCI
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 2d44933..d945c34 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -39,6 +39,10 @@ ifdef CONFIG_X86_NEED_RELOCS
         LDFLAGS_vmlinux := --emit-relocs
 endif
 
+ifdef CONFIG_X86_MULTIBOOT_STUB
+	LDFLAGS_vmlinux += -z max-page-size=0x1000
+endif
+
 #
 # Prevent GCC from generating any FP code by mistake.
 #
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 54a2372..c0f375a 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -29,6 +29,8 @@
 #include <asm/microcode.h>
 #include <asm/kasan.h>
 
+#include "multiboot2.h"
+
 /*
  * Manage page tables very early on.
  */
@@ -36,6 +38,7 @@ extern pgd_t early_level4_pgt[PTRS_PER_PGD];
 extern pmd_t early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
 static unsigned int __initdata next_early_pgt = 2;
 pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
+char *multiboot_info = NULL;
 
 /* Wipe all early page tables except for the kernel symbol map */
 static void __init reset_early_page_tables(void)
@@ -130,6 +133,60 @@ static void __init copy_bootdata(char *real_mode_data)
 	}
 }
 
+static void __init copy_multiboot_cmdline(struct multiboot_tag_string *tag)
+{
+	unsigned int size = tag->size - 8;
+
+	if (size > COMMAND_LINE_SIZE)
+		size = COMMAND_LINE_SIZE;
+	boot_params.hdr.cmdline_size = size;
+	memcpy(boot_command_line, tag->string, size);
+}
+
+static void __init copy_multiboot_mmap(struct multiboot_tag_mmap *tag)
+{
+	multiboot_memory_map_t *mmap;
+	int nr = 0;
+
+	for (mmap = tag->entries;
+		(u8 *)mmap < (u8 *)tag + tag->size && nr < E820MAX;
+		mmap = (multiboot_memory_map_t *)((unsigned long)mmap +
+							tag->entry_size)) {
+		boot_params.e820_map[nr].addr = mmap->addr;
+		boot_params.e820_map[nr].size = mmap->len;
+		boot_params.e820_map[nr].type = mmap->type;
+		nr++;
+	}
+	boot_params.e820_entries = nr;
+}
+
+static void __init copy_multiboot_info(void)
+{
+	struct multiboot_tag *tag;
+	char *ptr = __va(multiboot_info);
+
+	boot_params.hdr.boot_flag = 0xAA55;
+	boot_params.hdr.header = 0x53726448;
+	boot_params.hdr.version = 0x202;
+
+	for (tag = (struct multiboot_tag *)(ptr + 8);
+		tag->type != MULTIBOOT_TAG_TYPE_END;
+		tag = (struct multiboot_tag *)((u8 *) tag +
+						((tag->size + 7) & ~7))) {
+		switch (tag->type) {
+		case MULTIBOOT_TAG_TYPE_CMDLINE:
+			copy_multiboot_cmdline(
+					(struct multiboot_tag_string *)tag);
+			break;
+		case MULTIBOOT_TAG_TYPE_MMAP:
+			copy_multiboot_mmap((struct multiboot_tag_mmap *)tag);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 {
 	int i;
@@ -163,7 +220,12 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 		set_intr_gate(i, early_idt_handler_array[i]);
 	load_idt((const struct desc_ptr *)&idt_descr);
 
-	copy_bootdata(__va(real_mode_data));
+	if (multiboot_info) {
+		copy_multiboot_info();
+		real_mode_data = (char *) (__pa(&boot_params));
+	} else {
+		copy_bootdata(__va(real_mode_data));
+	}
 
 	/*
 	 * Load microcode early on BSP.
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index b4421cc..1c944fd 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -22,6 +22,7 @@
 #include <asm/nops.h>
 #include "../entry/calling.h"
 #include <asm/export.h>
+#include <asm/boot.h>
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/asm-offsets.h>
@@ -32,6 +33,8 @@
 #define INTERRUPT_RETURN iretq
 #endif
 
+#include "multiboot2.h"
+
 /* we are not able to switch in one step to the final KERNEL ADDRESS SPACE
  * because we need identity-mapped pages.
  *
@@ -66,6 +69,161 @@ startup_64:
 	 * tables and then reload them.
 	 */
 
+#ifdef CONFIG_X86_MULTIBOOT_STUB
+	jmp multiboot_entry
+
+	.align MULTIBOOT_HEADER_ALIGN
+multiboot_header:
+        /* magic */
+        .long	MULTIBOOT2_HEADER_MAGIC
+        /* ISA: i386 */
+        .long	MULTIBOOT_ARCHITECTURE_I386
+        /* Header length.  */
+        .long	multiboot_header_end - multiboot_header
+        /* checksum */
+        .long	-(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + \
+		(multiboot_header_end - multiboot_header))
+
+	/* information request tag */
+infomation_request_start:
+	.short	MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
+	.short	MULTIBOOT_HEADER_TAG_OPTIONAL
+	.long	infomation_request_end - infomation_request_start
+	.long	MULTIBOOT_TAG_TYPE_CMDLINE
+	.long	MULTIBOOT_TAG_TYPE_MMAP
+infomation_request_end:
+
+	.short MULTIBOOT_HEADER_TAG_END
+	.short 0
+	.long 8
+multiboot_header_end:
+
+multiboot_entry:
+	cmpl	$MULTIBOOT2_BOOTLOADER_MAGIC, %eax
+	jne	not_multiboot
+
+	.code32
+	/* %ebp contains the address we are loaded at by the boot loader */
+	movl $_text - __START_KERNEL_map, %ebp
+
+	/* Store the Multiboot information structure */
+	movl	%ebx, (multiboot_info - startup_64)(%ebp)
+
+	/*
+	 * The Multiboot-compliant bootloader puts the machine in 32-bit mode
+	 * so we need to switch to long mode by ourself. If later version of
+	 * Multiboot protocal supports 64-bit machine state then this part of
+	 * code may be eliminated.
+	 */
+	cli
+	movl	$(__BOOT_DS), %eax
+	movl	%eax, %ds
+	movl	%eax, %es
+	movl	%eax, %ss
+
+	/* Setup a stack and make sure cpu supports long mode. */
+	movl	(__end_init_task - 8 - startup_64)(%ebp), %eax
+	movl	%eax, %esp
+
+	call	verify_cpu
+	testl	%eax, %eax
+	jnz	no_longmode
+
+/*
+ * Prepare for entering 64 bit mode
+ */
+
+	/* Load new GDT with the 64bit segments using 32bit descriptor */
+	leal	(gdt - startup_64)(%ebp), %eax
+	movl	%eax, (gdt + 2 - startup_64)(%ebp)
+	lgdt	(gdt - startup_64)(%ebp)
+
+	/* Enable PAE mode */
+	movl	%cr4, %eax
+	orl	$X86_CR4_PAE, %eax
+	movl	%eax, %cr4
+
+ /*
+  * Build early 4G boot pagetable
+  */
+	/* Initialize Page tables to 0 */
+	/*leal	pgtable(%ebp), %edi
+	xorl	%eax, %eax
+	movl	$(BOOT_INIT_PGT_SIZE/4), %ecx
+	rep	stosl*/
+
+	/* Build Level 4 */
+	leal	(pgtable - startup_64)(%ebp), %edi
+	leal	0x1007 (%edi), %eax
+	movl	%eax, 0(%edi)
+
+	/* Build Level 3 */
+	leal	(pgtable + 0x1000 - startup_64)(%ebp), %edi
+	leal	0x1007(%edi), %eax
+	movl	$4, %ecx
+1:	movl	%eax, 0x00(%edi)
+	addl	$0x00001000, %eax
+	addl	$8, %edi
+	decl	%ecx
+	jnz	1b
+
+	/* Build Level 2 */
+	leal	(pgtable + 0x2000 - startup_64)(%ebp), %edi
+	movl	$0x00000183, %eax
+	movl	$2048, %ecx
+1:	movl	%eax, 0(%edi)
+	addl	$0x00200000, %eax
+	addl	$8, %edi
+	decl	%ecx
+	jnz	1b
+
+	/* Enable the boot page tables */
+	leal	(pgtable - startup_64)(%ebp), %eax
+	movl	%eax, %cr3
+
+	/* Enable Long mode in EFER (Extended Feature Enable Register) */
+	movl	$MSR_EFER, %ecx
+	rdmsr
+	btsl	$_EFER_LME, %eax
+	wrmsr
+
+	/* After gdt is loaded */
+	xorl	%eax, %eax
+	lldt	%ax
+	movl    $__BOOT_TSS, %eax
+	ltr	%ax
+
+	/*
+	 * Setup for the jump to 64bit mode
+	 *
+	 * When the jump is performend we will be in long mode but
+	 * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
+	 * (and in turn EFER.LMA = 1).	To jump into 64bit mode we use
+	 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
+	 * We place all of the values on our mini stack so lret can
+	 * used to perform that far jump.
+	 */
+	pushl	$__KERNEL_CS
+	leal	(not_multiboot - startup_64)(%ebp), %eax
+	pushl	%eax
+
+	/* Enter paged protected Mode, activating Long Mode */
+	movl	$(X86_CR0_PG | X86_CR0_PE), %eax /* Enable Paging and Protected mode */
+	movl	%eax, %cr0
+
+	/* Jump from 32bit compatibility mode into 64bit mode. */
+	lret
+
+no_longmode:
+	/* This isn't an x86-64 CPU so hang */
+1:
+	hlt
+	jmp     1b
+
+	.code64
+not_multiboot:
+#endif
+
 	/*
 	 * Setup stack for verify_cpu(). "-8" because initial_stack is defined
 	 * this way, see below. Our best guess is a NULL ptr for stack
@@ -489,6 +647,23 @@ ENTRY(phys_base)
 	.quad   0x0000000000000000
 EXPORT_SYMBOL(phys_base)
 
+#ifdef CONFIG_X86_MULTIBOOT_STUB
+gdt:
+	.word	gdt_end - gdt
+	.long	0
+	.word	0
+	.quad	0x0000000000000000	/* NULL descriptor */
+	.quad	0x00af9a000000ffff	/* __KERNEL_CS */
+	.quad	0x00cf92000000ffff	/* __KERNEL_DS */
+	.quad	0x0080890000000000	/* TS descriptor */
+	.quad   0x0000000000000000	/* TS continued */
+gdt_end:
+
+	.balign 4096
+pgtable:
+	.fill BOOT_PGT_SIZE, 1, 0
+#endif
+
 #include "../../x86/xen/xen-head.S"
 	
 	__PAGE_ALIGNED_BSS
diff --git a/arch/x86/kernel/multiboot2.h b/arch/x86/kernel/multiboot2.h
new file mode 100644
index 0000000..03bb5d2
--- /dev/null
+++ b/arch/x86/kernel/multiboot2.h
@@ -0,0 +1,417 @@
+/*  multiboot2.h - Multiboot 2 header file.  */
+/*  Copyright (C) 1999,2003,2007,2008,2009,2010  Free Software Foundation, Inc.
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to
+ *  deal in the Software without restriction, including without limitation the
+ *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ *  sell copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL ANY
+ *  DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ *  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _ARCH_X86_KERNEL_MULTIBOOT2
+#define _ARCH_X86_KERNEL_MULTIBOOT2
+
+/* How many bytes from the start of the file we search for the header.  */
+#define MULTIBOOT_SEARCH			32768
+#define MULTIBOOT_HEADER_ALIGN			8
+
+/* The magic field should contain this.  */
+#define MULTIBOOT2_HEADER_MAGIC			0xe85250d6
+
+/* This should be in %eax.  */
+#define MULTIBOOT2_BOOTLOADER_MAGIC		0x36d76289
+
+/* Alignment of multiboot modules.  */
+#define MULTIBOOT_MOD_ALIGN			0x00001000
+
+/* Alignment of the multiboot info structure.  */
+#define MULTIBOOT_INFO_ALIGN			0x00000008
+
+/* Flags set in the 'flags' member of the multiboot header.  */
+
+#define MULTIBOOT_TAG_ALIGN                  8
+#define MULTIBOOT_TAG_TYPE_END               0
+#define MULTIBOOT_TAG_TYPE_CMDLINE           1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME  2
+#define MULTIBOOT_TAG_TYPE_MODULE            3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO     4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV           5
+#define MULTIBOOT_TAG_TYPE_MMAP              6
+#define MULTIBOOT_TAG_TYPE_VBE               7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER       8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS      9
+#define MULTIBOOT_TAG_TYPE_APM               10
+#define MULTIBOOT_TAG_TYPE_EFI32             11
+#define MULTIBOOT_TAG_TYPE_EFI64             12
+#define MULTIBOOT_TAG_TYPE_SMBIOS            13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD          14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW          15
+#define MULTIBOOT_TAG_TYPE_NETWORK           16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP          17
+#define MULTIBOOT_TAG_TYPE_EFI_BS            18
+#define MULTIBOOT_TAG_TYPE_EFI32_IH          19
+#define MULTIBOOT_TAG_TYPE_EFI64_IH          20
+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR    21
+
+#define MULTIBOOT_HEADER_TAG_END  0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST  1
+#define MULTIBOOT_HEADER_TAG_ADDRESS  2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS  3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS  4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER  5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN  6
+#define MULTIBOOT_HEADER_TAG_EFI_BS        7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32  8
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64  9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE  10
+
+#define MULTIBOOT_ARCHITECTURE_I386  0
+#define MULTIBOOT_ARCHITECTURE_MIPS32  4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned char		multiboot_uint8_t;
+typedef unsigned short		multiboot_uint16_t;
+typedef unsigned int		multiboot_uint32_t;
+typedef unsigned long long	multiboot_uint64_t;
+
+struct multiboot_header
+{
+  /* Must be MULTIBOOT_MAGIC - see above.  */
+  multiboot_uint32_t magic;
+
+  /* ISA */
+  multiboot_uint32_t architecture;
+
+  /* Total header length.  */
+  multiboot_uint32_t header_length;
+
+  /* The above fields plus this one must equal 0 mod 2^32. */
+  multiboot_uint32_t checksum;
+};
+
+struct multiboot_header_tag
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_information_request
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t requests[0];
+};
+
+struct multiboot_header_tag_address
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t header_addr;
+  multiboot_uint32_t load_addr;
+  multiboot_uint32_t load_end_addr;
+  multiboot_uint32_t bss_end_addr;
+};
+
+struct multiboot_header_tag_entry_address
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t entry_addr;
+};
+
+struct multiboot_header_tag_console_flags
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t console_flags;
+};
+
+struct multiboot_header_tag_framebuffer
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t width;
+  multiboot_uint32_t height;
+  multiboot_uint32_t depth;
+};
+
+struct multiboot_header_tag_module_align
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_relocatable
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t min_addr;
+  multiboot_uint32_t max_addr;
+  multiboot_uint32_t align;
+  multiboot_uint32_t preference;
+};
+
+struct multiboot_color
+{
+  multiboot_uint8_t red;
+  multiboot_uint8_t green;
+  multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry
+{
+  multiboot_uint64_t addr;
+  multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE		1
+#define MULTIBOOT_MEMORY_RESERVED		2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE       3
+#define MULTIBOOT_MEMORY_NVS                    4
+#define MULTIBOOT_MEMORY_BADRAM                 5
+  multiboot_uint32_t type;
+  multiboot_uint32_t zero;
+};
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  char string[0];
+};
+
+struct multiboot_tag_module
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t mod_start;
+  multiboot_uint32_t mod_end;
+  char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t mem_lower;
+  multiboot_uint32_t mem_upper;
+};
+
+struct multiboot_tag_bootdev
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t biosdev;
+  multiboot_uint32_t slice;
+  multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t entry_size;
+  multiboot_uint32_t entry_version;
+  struct multiboot_mmap_entry entries[0];
+};
+
+struct multiboot_vbe_info_block
+{
+  multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+  multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
+  multiboot_uint16_t vbe_mode;
+  multiboot_uint16_t vbe_interface_seg;
+  multiboot_uint16_t vbe_interface_off;
+  multiboot_uint16_t vbe_interface_len;
+
+  struct multiboot_vbe_info_block vbe_control_info;
+  struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
+  multiboot_uint64_t framebuffer_addr;
+  multiboot_uint32_t framebuffer_pitch;
+  multiboot_uint32_t framebuffer_width;
+  multiboot_uint32_t framebuffer_height;
+  multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT	2
+  multiboot_uint8_t framebuffer_type;
+  multiboot_uint16_t reserved;
+};
+
+struct multiboot_tag_framebuffer
+{
+  struct multiboot_tag_framebuffer_common common;
+
+  union
+  {
+    struct
+    {
+      multiboot_uint16_t framebuffer_palette_num_colors;
+      struct multiboot_color framebuffer_palette[0];
+    };
+    struct
+    {
+      multiboot_uint8_t framebuffer_red_field_position;
+      multiboot_uint8_t framebuffer_red_mask_size;
+      multiboot_uint8_t framebuffer_green_field_position;
+      multiboot_uint8_t framebuffer_green_mask_size;
+      multiboot_uint8_t framebuffer_blue_field_position;
+      multiboot_uint8_t framebuffer_blue_mask_size;
+    };
+  };
+};
+
+struct multiboot_tag_elf_sections
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t num;
+  multiboot_uint32_t entsize;
+  multiboot_uint32_t shndx;
+  char sections[0];
+};
+
+struct multiboot_tag_apm
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint16_t version;
+  multiboot_uint16_t cseg;
+  multiboot_uint32_t offset;
+  multiboot_uint16_t cseg_16;
+  multiboot_uint16_t dseg;
+  multiboot_uint16_t flags;
+  multiboot_uint16_t cseg_len;
+  multiboot_uint16_t cseg_16_len;
+  multiboot_uint16_t dseg_len;
+};
+
+struct multiboot_tag_efi32
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_smbios
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint8_t major;
+  multiboot_uint8_t minor;
+  multiboot_uint8_t reserved[6];
+  multiboot_uint8_t tables[0];
+};
+
+struct multiboot_tag_old_acpi
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_new_acpi
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_network
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint8_t dhcpack[0];
+};
+
+struct multiboot_tag_efi_mmap
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t descr_size;
+  multiboot_uint32_t descr_vers;
+  multiboot_uint8_t efi_mmap[0];
+};
+
+struct multiboot_tag_efi32_ih
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64_ih
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_load_base_addr
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t load_base_addr;
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ARCH_X86_KERNEL_MULTIBOOT2 */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-15 14:41 [RFC PATCH] x86/boot: make ELF kernel multiboot-able Chao Peng
@ 2017-02-15 16:42 ` Paolo Bonzini
  2017-02-16  2:12   ` Chao Peng
  2017-02-15 18:12 ` hpa
  1 sibling, 1 reply; 10+ messages in thread
From: Paolo Bonzini @ 2017-02-15 16:42 UTC (permalink / raw)
  To: Chao Peng, linux-kernel, x86, grub-devel
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Andy Lutomirski,
	Juergen Gross, Luis R. Rodriguez, Borislav Petkov,
	Josh Poimboeuf, Thomas Garnier, Al Viro, Michael S. Tsirkin,
	Amnon Ilan



On 15/02/2017 15:41, Chao Peng wrote:
> Multiboot specification (http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.texi?h=multiboot2)
> is an open standard that provides kernels with a uniform way to be booted
> by multiboot-compliant bootloaders (like grub).
> 
> This patch is trying to make Linux ELF kernel image to be a
> multiboot-compliant OS so that it can be loaded by a multiboot-comliant
> bootloader. The benefit is eliminating the maintainance for realmode and
> decompression code and especially when the kernel is loaded in a virtual
> machine, the reducing for these code can greatly cuts down the boot time.
> 
> However, the current version of multiboot spec doesn't support 64 bit
> well so for 64 bit kernel we need stub code to jump from 32 bit code to
> 64 bit code. Besides, there are still some other issues:
>   1). '-z max-page-size=0x1000' is used so the text segment start is in
>   multiboot header search scope because GNU LD has default page size of
>   0x00200000 for ELF64, which will fail multiboot test.
> 
>   2). The bootloader like grub has support for ELF kernel (even for ELF64)
>   which makes the patch easier. However, the current grub implementaion
>   thinks the entry address should be a VA. E.g. for 64 bit kernel, the entry
>   address (0x1000000) is actually phiscial address, grub refuses to load it
>   by saying: 'entry point isn't in a segment'.

For kvm-unit-tests, we do "objcopy -O elf32-i386 dest.32bit dest.64bit"
and pass the resulting 32bit ELF file to grub.

Out of curiosity, what happens if you pass the resulting multiboot file
to QEMU's -kernel option?

Thanks,

Paolo

> This patch is sent out as RFC in case you have some ideas.
> 
> Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-15 14:41 [RFC PATCH] x86/boot: make ELF kernel multiboot-able Chao Peng
  2017-02-15 16:42 ` Paolo Bonzini
@ 2017-02-15 18:12 ` hpa
  2017-02-15 20:13   ` Luis R. Rodriguez
  1 sibling, 1 reply; 10+ messages in thread
From: hpa @ 2017-02-15 18:12 UTC (permalink / raw)
  To: Chao Peng, linux-kernel, x86, grub-devel
  Cc: Thomas Gleixner, Ingo Molnar, Andy Lutomirski, Juergen Gross,
	Luis R. Rodriguez, Borislav Petkov, Josh Poimboeuf,
	Thomas Garnier, Al Viro, Michael S. Tsirkin, Paolo Bonzini,
	Amnon Ilan

On February 15, 2017 6:41:56 AM PST, Chao Peng <chao.p.peng@linux.intel.com> wrote:
>Multiboot specification
>(http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.texi?h=multiboot2)
>is an open standard that provides kernels with a uniform way to be
>booted
>by multiboot-compliant bootloaders (like grub).
>
>This patch is trying to make Linux ELF kernel image to be a
>multiboot-compliant OS so that it can be loaded by a multiboot-comliant
>bootloader. The benefit is eliminating the maintainance for realmode
>and
>decompression code and especially when the kernel is loaded in a
>virtual
>machine, the reducing for these code can greatly cuts down the boot
>time.
>
>However, the current version of multiboot spec doesn't support 64 bit
>well so for 64 bit kernel we need stub code to jump from 32 bit code to
>64 bit code. Besides, there are still some other issues:
>  1). '-z max-page-size=0x1000' is used so the text segment start is in
>  multiboot header search scope because GNU LD has default page size of
>  0x00200000 for ELF64, which will fail multiboot test.
>
>2). The bootloader like grub has support for ELF kernel (even for
>ELF64)
>  which makes the patch easier. However, the current grub implementaion
>thinks the entry address should be a VA. E.g. for 64 bit kernel, the
>entry
>address (0x1000000) is actually phiscial address, grub refuses to load
>it
>  by saying: 'entry point isn't in a segment'.
>
>This patch is sent out as RFC in case you have some ideas.
>
>Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
>---
> arch/x86/Kconfig             |   6 +
> arch/x86/Makefile            |   4 +
> arch/x86/kernel/head64.c     |  64 ++++++-
> arch/x86/kernel/head_64.S    | 175 ++++++++++++++++++
>arch/x86/kernel/multiboot2.h | 417
>+++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 665 insertions(+), 1 deletion(-)
> create mode 100644 arch/x86/kernel/multiboot2.h
>
>diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>index bada636..75a9ef2 100644
>--- a/arch/x86/Kconfig
>+++ b/arch/x86/Kconfig
>@@ -585,6 +585,12 @@ config X86_AMD_PLATFORM_DEVICE
> 	  I2C and UART depend on COMMON_CLK to set clock. GPIO driver is
> 	  implemented under PINCTRL subsystem.
> 
>+config X86_MULTIBOOT_STUB
>+	bool "Multiboot stub support for ELF kernel image"
>+	default n
>+	---help---
>+	  Set whether multiboot stub is on or off.
>+
> config IOSF_MBI
> 	tristate "Intel SoC IOSF Sideband support for SoC platforms"
> 	depends on PCI
>diff --git a/arch/x86/Makefile b/arch/x86/Makefile
>index 2d44933..d945c34 100644
>--- a/arch/x86/Makefile
>+++ b/arch/x86/Makefile
>@@ -39,6 +39,10 @@ ifdef CONFIG_X86_NEED_RELOCS
>         LDFLAGS_vmlinux := --emit-relocs
> endif
> 
>+ifdef CONFIG_X86_MULTIBOOT_STUB
>+	LDFLAGS_vmlinux += -z max-page-size=0x1000
>+endif
>+
> #
> # Prevent GCC from generating any FP code by mistake.
> #
>diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
>index 54a2372..c0f375a 100644
>--- a/arch/x86/kernel/head64.c
>+++ b/arch/x86/kernel/head64.c
>@@ -29,6 +29,8 @@
> #include <asm/microcode.h>
> #include <asm/kasan.h>
> 
>+#include "multiboot2.h"
>+
> /*
>  * Manage page tables very early on.
>  */
>@@ -36,6 +38,7 @@ extern pgd_t early_level4_pgt[PTRS_PER_PGD];
>extern pmd_t
>early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
> static unsigned int __initdata next_early_pgt = 2;
>pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL |
>_PAGE_NX);
>+char *multiboot_info = NULL;
> 
> /* Wipe all early page tables except for the kernel symbol map */
> static void __init reset_early_page_tables(void)
>@@ -130,6 +133,60 @@ static void __init copy_bootdata(char
>*real_mode_data)
> 	}
> }
> 
>+static void __init copy_multiboot_cmdline(struct multiboot_tag_string
>*tag)
>+{
>+	unsigned int size = tag->size - 8;
>+
>+	if (size > COMMAND_LINE_SIZE)
>+		size = COMMAND_LINE_SIZE;
>+	boot_params.hdr.cmdline_size = size;
>+	memcpy(boot_command_line, tag->string, size);
>+}
>+
>+static void __init copy_multiboot_mmap(struct multiboot_tag_mmap *tag)
>+{
>+	multiboot_memory_map_t *mmap;
>+	int nr = 0;
>+
>+	for (mmap = tag->entries;
>+		(u8 *)mmap < (u8 *)tag + tag->size && nr < E820MAX;
>+		mmap = (multiboot_memory_map_t *)((unsigned long)mmap +
>+							tag->entry_size)) {
>+		boot_params.e820_map[nr].addr = mmap->addr;
>+		boot_params.e820_map[nr].size = mmap->len;
>+		boot_params.e820_map[nr].type = mmap->type;
>+		nr++;
>+	}
>+	boot_params.e820_entries = nr;
>+}
>+
>+static void __init copy_multiboot_info(void)
>+{
>+	struct multiboot_tag *tag;
>+	char *ptr = __va(multiboot_info);
>+
>+	boot_params.hdr.boot_flag = 0xAA55;
>+	boot_params.hdr.header = 0x53726448;
>+	boot_params.hdr.version = 0x202;
>+
>+	for (tag = (struct multiboot_tag *)(ptr + 8);
>+		tag->type != MULTIBOOT_TAG_TYPE_END;
>+		tag = (struct multiboot_tag *)((u8 *) tag +
>+						((tag->size + 7) & ~7))) {
>+		switch (tag->type) {
>+		case MULTIBOOT_TAG_TYPE_CMDLINE:
>+			copy_multiboot_cmdline(
>+					(struct multiboot_tag_string *)tag);
>+			break;
>+		case MULTIBOOT_TAG_TYPE_MMAP:
>+			copy_multiboot_mmap((struct multiboot_tag_mmap *)tag);
>+			break;
>+		default:
>+			break;
>+		}
>+	}
>+}
>+
>asmlinkage __visible void __init x86_64_start_kernel(char *
>real_mode_data)
> {
> 	int i;
>@@ -163,7 +220,12 @@ asmlinkage __visible void __init
>x86_64_start_kernel(char * real_mode_data)
> 		set_intr_gate(i, early_idt_handler_array[i]);
> 	load_idt((const struct desc_ptr *)&idt_descr);
> 
>-	copy_bootdata(__va(real_mode_data));
>+	if (multiboot_info) {
>+		copy_multiboot_info();
>+		real_mode_data = (char *) (__pa(&boot_params));
>+	} else {
>+		copy_bootdata(__va(real_mode_data));
>+	}
> 
> 	/*
> 	 * Load microcode early on BSP.
>diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
>index b4421cc..1c944fd 100644
>--- a/arch/x86/kernel/head_64.S
>+++ b/arch/x86/kernel/head_64.S
>@@ -22,6 +22,7 @@
> #include <asm/nops.h>
> #include "../entry/calling.h"
> #include <asm/export.h>
>+#include <asm/boot.h>
> 
> #ifdef CONFIG_PARAVIRT
> #include <asm/asm-offsets.h>
>@@ -32,6 +33,8 @@
> #define INTERRUPT_RETURN iretq
> #endif
> 
>+#include "multiboot2.h"
>+
>/* we are not able to switch in one step to the final KERNEL ADDRESS
>SPACE
>  * because we need identity-mapped pages.
>  *
>@@ -66,6 +69,161 @@ startup_64:
> 	 * tables and then reload them.
> 	 */
> 
>+#ifdef CONFIG_X86_MULTIBOOT_STUB
>+	jmp multiboot_entry
>+
>+	.align MULTIBOOT_HEADER_ALIGN
>+multiboot_header:
>+        /* magic */
>+        .long	MULTIBOOT2_HEADER_MAGIC
>+        /* ISA: i386 */
>+        .long	MULTIBOOT_ARCHITECTURE_I386
>+        /* Header length.  */
>+        .long	multiboot_header_end - multiboot_header
>+        /* checksum */
>+        .long	-(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386
>+ \
>+		(multiboot_header_end - multiboot_header))
>+
>+	/* information request tag */
>+infomation_request_start:
>+	.short	MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
>+	.short	MULTIBOOT_HEADER_TAG_OPTIONAL
>+	.long	infomation_request_end - infomation_request_start
>+	.long	MULTIBOOT_TAG_TYPE_CMDLINE
>+	.long	MULTIBOOT_TAG_TYPE_MMAP
>+infomation_request_end:
>+
>+	.short MULTIBOOT_HEADER_TAG_END
>+	.short 0
>+	.long 8
>+multiboot_header_end:
>+
>+multiboot_entry:
>+	cmpl	$MULTIBOOT2_BOOTLOADER_MAGIC, %eax
>+	jne	not_multiboot
>+
>+	.code32
>+	/* %ebp contains the address we are loaded at by the boot loader */
>+	movl $_text - __START_KERNEL_map, %ebp
>+
>+	/* Store the Multiboot information structure */
>+	movl	%ebx, (multiboot_info - startup_64)(%ebp)
>+
>+	/*
>+	 * The Multiboot-compliant bootloader puts the machine in 32-bit mode
>+	 * so we need to switch to long mode by ourself. If later version of
>+	 * Multiboot protocal supports 64-bit machine state then this part of
>+	 * code may be eliminated.
>+	 */
>+	cli
>+	movl	$(__BOOT_DS), %eax
>+	movl	%eax, %ds
>+	movl	%eax, %es
>+	movl	%eax, %ss
>+
>+	/* Setup a stack and make sure cpu supports long mode. */
>+	movl	(__end_init_task - 8 - startup_64)(%ebp), %eax
>+	movl	%eax, %esp
>+
>+	call	verify_cpu
>+	testl	%eax, %eax
>+	jnz	no_longmode
>+
>+/*
>+ * Prepare for entering 64 bit mode
>+ */
>+
>+	/* Load new GDT with the 64bit segments using 32bit descriptor */
>+	leal	(gdt - startup_64)(%ebp), %eax
>+	movl	%eax, (gdt + 2 - startup_64)(%ebp)
>+	lgdt	(gdt - startup_64)(%ebp)
>+
>+	/* Enable PAE mode */
>+	movl	%cr4, %eax
>+	orl	$X86_CR4_PAE, %eax
>+	movl	%eax, %cr4
>+
>+ /*
>+  * Build early 4G boot pagetable
>+  */
>+	/* Initialize Page tables to 0 */
>+	/*leal	pgtable(%ebp), %edi
>+	xorl	%eax, %eax
>+	movl	$(BOOT_INIT_PGT_SIZE/4), %ecx
>+	rep	stosl*/
>+
>+	/* Build Level 4 */
>+	leal	(pgtable - startup_64)(%ebp), %edi
>+	leal	0x1007 (%edi), %eax
>+	movl	%eax, 0(%edi)
>+
>+	/* Build Level 3 */
>+	leal	(pgtable + 0x1000 - startup_64)(%ebp), %edi
>+	leal	0x1007(%edi), %eax
>+	movl	$4, %ecx
>+1:	movl	%eax, 0x00(%edi)
>+	addl	$0x00001000, %eax
>+	addl	$8, %edi
>+	decl	%ecx
>+	jnz	1b
>+
>+	/* Build Level 2 */
>+	leal	(pgtable + 0x2000 - startup_64)(%ebp), %edi
>+	movl	$0x00000183, %eax
>+	movl	$2048, %ecx
>+1:	movl	%eax, 0(%edi)
>+	addl	$0x00200000, %eax
>+	addl	$8, %edi
>+	decl	%ecx
>+	jnz	1b
>+
>+	/* Enable the boot page tables */
>+	leal	(pgtable - startup_64)(%ebp), %eax
>+	movl	%eax, %cr3
>+
>+	/* Enable Long mode in EFER (Extended Feature Enable Register) */
>+	movl	$MSR_EFER, %ecx
>+	rdmsr
>+	btsl	$_EFER_LME, %eax
>+	wrmsr
>+
>+	/* After gdt is loaded */
>+	xorl	%eax, %eax
>+	lldt	%ax
>+	movl    $__BOOT_TSS, %eax
>+	ltr	%ax
>+
>+	/*
>+	 * Setup for the jump to 64bit mode
>+	 *
>+	 * When the jump is performend we will be in long mode but
>+	 * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
>+	 * (and in turn EFER.LMA = 1).	To jump into 64bit mode we use
>+	 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
>+	 * We place all of the values on our mini stack so lret can
>+	 * used to perform that far jump.
>+	 */
>+	pushl	$__KERNEL_CS
>+	leal	(not_multiboot - startup_64)(%ebp), %eax
>+	pushl	%eax
>+
>+	/* Enter paged protected Mode, activating Long Mode */
>+	movl	$(X86_CR0_PG | X86_CR0_PE), %eax /* Enable Paging and Protected
>mode */
>+	movl	%eax, %cr0
>+
>+	/* Jump from 32bit compatibility mode into 64bit mode. */
>+	lret
>+
>+no_longmode:
>+	/* This isn't an x86-64 CPU so hang */
>+1:
>+	hlt
>+	jmp     1b
>+
>+	.code64
>+not_multiboot:
>+#endif
>+
> 	/*
>	 * Setup stack for verify_cpu(). "-8" because initial_stack is defined
> 	 * this way, see below. Our best guess is a NULL ptr for stack
>@@ -489,6 +647,23 @@ ENTRY(phys_base)
> 	.quad   0x0000000000000000
> EXPORT_SYMBOL(phys_base)
> 
>+#ifdef CONFIG_X86_MULTIBOOT_STUB
>+gdt:
>+	.word	gdt_end - gdt
>+	.long	0
>+	.word	0
>+	.quad	0x0000000000000000	/* NULL descriptor */
>+	.quad	0x00af9a000000ffff	/* __KERNEL_CS */
>+	.quad	0x00cf92000000ffff	/* __KERNEL_DS */
>+	.quad	0x0080890000000000	/* TS descriptor */
>+	.quad   0x0000000000000000	/* TS continued */
>+gdt_end:
>+
>+	.balign 4096
>+pgtable:
>+	.fill BOOT_PGT_SIZE, 1, 0
>+#endif
>+
> #include "../../x86/xen/xen-head.S"
> 	
> 	__PAGE_ALIGNED_BSS
>diff --git a/arch/x86/kernel/multiboot2.h
>b/arch/x86/kernel/multiboot2.h
>new file mode 100644
>index 0000000..03bb5d2
>--- /dev/null
>+++ b/arch/x86/kernel/multiboot2.h
>@@ -0,0 +1,417 @@
>+/*  multiboot2.h - Multiboot 2 header file.  */
>+/*  Copyright (C) 1999,2003,2007,2008,2009,2010  Free Software
>Foundation, Inc.
>+ *
>+ *  Permission is hereby granted, free of charge, to any person
>obtaining a copy
>+ *  of this software and associated documentation files (the
>"Software"), to
>+ *  deal in the Software without restriction, including without
>limitation the
>+ *  rights to use, copy, modify, merge, publish, distribute,
>sublicense, and/or
>+ *  sell copies of the Software, and to permit persons to whom the
>Software is
>+ *  furnished to do so, subject to the following conditions:
>+ *
>+ *  The above copyright notice and this permission notice shall be
>included in
>+ *  all copies or substantial portions of the Software.
>+ *
>+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>EXPRESS OR
>+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>MERCHANTABILITY,
>+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
>SHALL ANY
>+ *  DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>LIABILITY,
>+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>OUT OF OR
>+ *  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>THE SOFTWARE.
>+ */
>+
>+#ifndef _ARCH_X86_KERNEL_MULTIBOOT2
>+#define _ARCH_X86_KERNEL_MULTIBOOT2
>+
>+/* How many bytes from the start of the file we search for the header.
> */
>+#define MULTIBOOT_SEARCH			32768
>+#define MULTIBOOT_HEADER_ALIGN			8
>+
>+/* The magic field should contain this.  */
>+#define MULTIBOOT2_HEADER_MAGIC			0xe85250d6
>+
>+/* This should be in %eax.  */
>+#define MULTIBOOT2_BOOTLOADER_MAGIC		0x36d76289
>+
>+/* Alignment of multiboot modules.  */
>+#define MULTIBOOT_MOD_ALIGN			0x00001000
>+
>+/* Alignment of the multiboot info structure.  */
>+#define MULTIBOOT_INFO_ALIGN			0x00000008
>+
>+/* Flags set in the 'flags' member of the multiboot header.  */
>+
>+#define MULTIBOOT_TAG_ALIGN                  8
>+#define MULTIBOOT_TAG_TYPE_END               0
>+#define MULTIBOOT_TAG_TYPE_CMDLINE           1
>+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME  2
>+#define MULTIBOOT_TAG_TYPE_MODULE            3
>+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO     4
>+#define MULTIBOOT_TAG_TYPE_BOOTDEV           5
>+#define MULTIBOOT_TAG_TYPE_MMAP              6
>+#define MULTIBOOT_TAG_TYPE_VBE               7
>+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER       8
>+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS      9
>+#define MULTIBOOT_TAG_TYPE_APM               10
>+#define MULTIBOOT_TAG_TYPE_EFI32             11
>+#define MULTIBOOT_TAG_TYPE_EFI64             12
>+#define MULTIBOOT_TAG_TYPE_SMBIOS            13
>+#define MULTIBOOT_TAG_TYPE_ACPI_OLD          14
>+#define MULTIBOOT_TAG_TYPE_ACPI_NEW          15
>+#define MULTIBOOT_TAG_TYPE_NETWORK           16
>+#define MULTIBOOT_TAG_TYPE_EFI_MMAP          17
>+#define MULTIBOOT_TAG_TYPE_EFI_BS            18
>+#define MULTIBOOT_TAG_TYPE_EFI32_IH          19
>+#define MULTIBOOT_TAG_TYPE_EFI64_IH          20
>+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR    21
>+
>+#define MULTIBOOT_HEADER_TAG_END  0
>+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST  1
>+#define MULTIBOOT_HEADER_TAG_ADDRESS  2
>+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS  3
>+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS  4
>+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER  5
>+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN  6
>+#define MULTIBOOT_HEADER_TAG_EFI_BS        7
>+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32  8
>+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64  9
>+#define MULTIBOOT_HEADER_TAG_RELOCATABLE  10
>+
>+#define MULTIBOOT_ARCHITECTURE_I386  0
>+#define MULTIBOOT_ARCHITECTURE_MIPS32  4
>+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
>+
>+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
>+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
>+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
>+
>+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
>+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
>+
>+#ifndef __ASSEMBLY__
>+
>+typedef unsigned char		multiboot_uint8_t;
>+typedef unsigned short		multiboot_uint16_t;
>+typedef unsigned int		multiboot_uint32_t;
>+typedef unsigned long long	multiboot_uint64_t;
>+
>+struct multiboot_header
>+{
>+  /* Must be MULTIBOOT_MAGIC - see above.  */
>+  multiboot_uint32_t magic;
>+
>+  /* ISA */
>+  multiboot_uint32_t architecture;
>+
>+  /* Total header length.  */
>+  multiboot_uint32_t header_length;
>+
>+  /* The above fields plus this one must equal 0 mod 2^32. */
>+  multiboot_uint32_t checksum;
>+};
>+
>+struct multiboot_header_tag
>+{
>+  multiboot_uint16_t type;
>+  multiboot_uint16_t flags;
>+  multiboot_uint32_t size;
>+};
>+
>+struct multiboot_header_tag_information_request
>+{
>+  multiboot_uint16_t type;
>+  multiboot_uint16_t flags;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t requests[0];
>+};
>+
>+struct multiboot_header_tag_address
>+{
>+  multiboot_uint16_t type;
>+  multiboot_uint16_t flags;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t header_addr;
>+  multiboot_uint32_t load_addr;
>+  multiboot_uint32_t load_end_addr;
>+  multiboot_uint32_t bss_end_addr;
>+};
>+
>+struct multiboot_header_tag_entry_address
>+{
>+  multiboot_uint16_t type;
>+  multiboot_uint16_t flags;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t entry_addr;
>+};
>+
>+struct multiboot_header_tag_console_flags
>+{
>+  multiboot_uint16_t type;
>+  multiboot_uint16_t flags;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t console_flags;
>+};
>+
>+struct multiboot_header_tag_framebuffer
>+{
>+  multiboot_uint16_t type;
>+  multiboot_uint16_t flags;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t width;
>+  multiboot_uint32_t height;
>+  multiboot_uint32_t depth;
>+};
>+
>+struct multiboot_header_tag_module_align
>+{
>+  multiboot_uint16_t type;
>+  multiboot_uint16_t flags;
>+  multiboot_uint32_t size;
>+};
>+
>+struct multiboot_header_tag_relocatable
>+{
>+  multiboot_uint16_t type;
>+  multiboot_uint16_t flags;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t min_addr;
>+  multiboot_uint32_t max_addr;
>+  multiboot_uint32_t align;
>+  multiboot_uint32_t preference;
>+};
>+
>+struct multiboot_color
>+{
>+  multiboot_uint8_t red;
>+  multiboot_uint8_t green;
>+  multiboot_uint8_t blue;
>+};
>+
>+struct multiboot_mmap_entry
>+{
>+  multiboot_uint64_t addr;
>+  multiboot_uint64_t len;
>+#define MULTIBOOT_MEMORY_AVAILABLE		1
>+#define MULTIBOOT_MEMORY_RESERVED		2
>+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE       3
>+#define MULTIBOOT_MEMORY_NVS                    4
>+#define MULTIBOOT_MEMORY_BADRAM                 5
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t zero;
>+};
>+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
>+
>+struct multiboot_tag
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+};
>+
>+struct multiboot_tag_string
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  char string[0];
>+};
>+
>+struct multiboot_tag_module
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t mod_start;
>+  multiboot_uint32_t mod_end;
>+  char cmdline[0];
>+};
>+
>+struct multiboot_tag_basic_meminfo
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t mem_lower;
>+  multiboot_uint32_t mem_upper;
>+};
>+
>+struct multiboot_tag_bootdev
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t biosdev;
>+  multiboot_uint32_t slice;
>+  multiboot_uint32_t part;
>+};
>+
>+struct multiboot_tag_mmap
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t entry_size;
>+  multiboot_uint32_t entry_version;
>+  struct multiboot_mmap_entry entries[0];
>+};
>+
>+struct multiboot_vbe_info_block
>+{
>+  multiboot_uint8_t external_specification[512];
>+};
>+
>+struct multiboot_vbe_mode_info_block
>+{
>+  multiboot_uint8_t external_specification[256];
>+};
>+
>+struct multiboot_tag_vbe
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+
>+  multiboot_uint16_t vbe_mode;
>+  multiboot_uint16_t vbe_interface_seg;
>+  multiboot_uint16_t vbe_interface_off;
>+  multiboot_uint16_t vbe_interface_len;
>+
>+  struct multiboot_vbe_info_block vbe_control_info;
>+  struct multiboot_vbe_mode_info_block vbe_mode_info;
>+};
>+
>+struct multiboot_tag_framebuffer_common
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+
>+  multiboot_uint64_t framebuffer_addr;
>+  multiboot_uint32_t framebuffer_pitch;
>+  multiboot_uint32_t framebuffer_width;
>+  multiboot_uint32_t framebuffer_height;
>+  multiboot_uint8_t framebuffer_bpp;
>+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
>+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
>+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT	2
>+  multiboot_uint8_t framebuffer_type;
>+  multiboot_uint16_t reserved;
>+};
>+
>+struct multiboot_tag_framebuffer
>+{
>+  struct multiboot_tag_framebuffer_common common;
>+
>+  union
>+  {
>+    struct
>+    {
>+      multiboot_uint16_t framebuffer_palette_num_colors;
>+      struct multiboot_color framebuffer_palette[0];
>+    };
>+    struct
>+    {
>+      multiboot_uint8_t framebuffer_red_field_position;
>+      multiboot_uint8_t framebuffer_red_mask_size;
>+      multiboot_uint8_t framebuffer_green_field_position;
>+      multiboot_uint8_t framebuffer_green_mask_size;
>+      multiboot_uint8_t framebuffer_blue_field_position;
>+      multiboot_uint8_t framebuffer_blue_mask_size;
>+    };
>+  };
>+};
>+
>+struct multiboot_tag_elf_sections
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t num;
>+  multiboot_uint32_t entsize;
>+  multiboot_uint32_t shndx;
>+  char sections[0];
>+};
>+
>+struct multiboot_tag_apm
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint16_t version;
>+  multiboot_uint16_t cseg;
>+  multiboot_uint32_t offset;
>+  multiboot_uint16_t cseg_16;
>+  multiboot_uint16_t dseg;
>+  multiboot_uint16_t flags;
>+  multiboot_uint16_t cseg_len;
>+  multiboot_uint16_t cseg_16_len;
>+  multiboot_uint16_t dseg_len;
>+};
>+
>+struct multiboot_tag_efi32
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t pointer;
>+};
>+
>+struct multiboot_tag_efi64
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint64_t pointer;
>+};
>+
>+struct multiboot_tag_smbios
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint8_t major;
>+  multiboot_uint8_t minor;
>+  multiboot_uint8_t reserved[6];
>+  multiboot_uint8_t tables[0];
>+};
>+
>+struct multiboot_tag_old_acpi
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint8_t rsdp[0];
>+};
>+
>+struct multiboot_tag_new_acpi
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint8_t rsdp[0];
>+};
>+
>+struct multiboot_tag_network
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint8_t dhcpack[0];
>+};
>+
>+struct multiboot_tag_efi_mmap
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t descr_size;
>+  multiboot_uint32_t descr_vers;
>+  multiboot_uint8_t efi_mmap[0];
>+};
>+
>+struct multiboot_tag_efi32_ih
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t pointer;
>+};
>+
>+struct multiboot_tag_efi64_ih
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint64_t pointer;
>+};
>+
>+struct multiboot_tag_load_base_addr
>+{
>+  multiboot_uint32_t type;
>+  multiboot_uint32_t size;
>+  multiboot_uint32_t load_base_addr;
>+};
>+
>+#endif /* __ASSEMBLY__ */
>+
>+#endif /* _ARCH_X86_KERNEL_MULTIBOOT2 */

As has been shown many times before, this is a really bad idea.  Unless there is a real-life use case where this matters enormously, this is nacked with extreme prejudice.
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-15 18:12 ` hpa
@ 2017-02-15 20:13   ` Luis R. Rodriguez
  2017-02-15 20:58     ` hpa
  0 siblings, 1 reply; 10+ messages in thread
From: Luis R. Rodriguez @ 2017-02-15 20:13 UTC (permalink / raw)
  To: hpa
  Cc: Chao Peng, linux-kernel, x86, grub-devel, Thomas Gleixner,
	Ingo Molnar, Andy Lutomirski, Juergen Gross, Luis R. Rodriguez,
	Borislav Petkov, Josh Poimboeuf, Thomas Garnier, Al Viro,
	Michael S. Tsirkin, Paolo Bonzini, Amnon Ilan, Alexander Graf,
	Matt Fleming, Daniel Kiper

On Wed, Feb 15, 2017 at 10:12:07AM -0800, hpa@zytor.com wrote:
> On February 15, 2017 6:41:56 AM PST, Chao Peng <chao.p.peng@linux.intel.com> wrote:
> >Multiboot specification
> >(http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.texi?h=multiboot2)
> >is an open standard that provides kernels with a uniform way to be booted
> >by multiboot-compliant bootloaders (like grub).
> >
> >This patch is trying to make Linux ELF kernel image to be a
> >multiboot-compliant OS so that it can be loaded by a multiboot-comliant
> >bootloader. The benefit is eliminating the maintainance for realmode and
> >decompression code and especially when the kernel is loaded in a virtual
> >machine, the reducing for these code can greatly cuts down the boot time.
> >
> >However, the current version of multiboot spec doesn't support 64 bit well
> >so for 64 bit kernel we need stub code to jump from 32 bit code to 64 bit
> >code. Besides, there are still some other issues:
> >
> >1). '-z max-page-size=0x1000' is used so the text segment start is in
> >multiboot header search scope because GNU LD has default page size of
> >0x00200000 for ELF64, which will fail multiboot test.
> >
> >2). The bootloader like grub has support for ELF kernel (even for ELF64)
> >which makes the patch easier. However, the current grub implementaion thinks
> >the entry address should be a VA. E.g. for 64 bit kernel, the entry address
> >(0x1000000) is actually phiscial address, grub refuses to load it by saying:
> >'entry point isn't in a segment'.
> >
> >This patch is sent out as RFC in case you have some ideas.
> >
> >Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
> 
> As has been shown many times before, this is a really bad idea.  Unless there
> is a real-life use case where this matters enormously, this is nacked with
> extreme prejudice.

Just something to consider, provided the issues with multiboot get resolved:

If you want to boot Xen you actually use the multiboot protocol, the last PVH
boot patches had borrowed ideas from Multiboot to add an entry to Linux, only
it was Xen'ified. What would be Multiboot 2 seemed flexible enough to allow all
sorts of custom semantics and information stacked into a boot image. The last
thought I had over this topic (before giving up)  was-- if we're going to add
yet-another-entry (TM) why not add extend Mulitiboot 2 protocol with the
semantics we need to boot any virtual environment and then add Multiboot 2
support entry on Linux? We could redirect any custom boot mechanism then to
just use that given its flexibility.

  Luis

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-15 20:13   ` Luis R. Rodriguez
@ 2017-02-15 20:58     ` hpa
  2017-02-16  2:07       ` Chao Peng
  2017-02-16 23:27       ` Daniel Kiper
  0 siblings, 2 replies; 10+ messages in thread
From: hpa @ 2017-02-15 20:58 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Chao Peng, linux-kernel, x86, grub-devel, Thomas Gleixner,
	Ingo Molnar, Andy Lutomirski, Juergen Gross, Borislav Petkov,
	Josh Poimboeuf, Thomas Garnier, Al Viro, Michael S. Tsirkin,
	Paolo Bonzini, Amnon Ilan, Alexander Graf, Matt Fleming,
	Daniel Kiper

On February 15, 2017 12:13:36 PM PST, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>On Wed, Feb 15, 2017 at 10:12:07AM -0800, hpa@zytor.com wrote:
>> On February 15, 2017 6:41:56 AM PST, Chao Peng
><chao.p.peng@linux.intel.com> wrote:
>> >Multiboot specification
>>
>>(http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.texi?h=multiboot2)
>> >is an open standard that provides kernels with a uniform way to be
>booted
>> >by multiboot-compliant bootloaders (like grub).
>> >
>> >This patch is trying to make Linux ELF kernel image to be a
>> >multiboot-compliant OS so that it can be loaded by a
>multiboot-comliant
>> >bootloader. The benefit is eliminating the maintainance for realmode
>and
>> >decompression code and especially when the kernel is loaded in a
>virtual
>> >machine, the reducing for these code can greatly cuts down the boot
>time.
>> >
>> >However, the current version of multiboot spec doesn't support 64
>bit well
>> >so for 64 bit kernel we need stub code to jump from 32 bit code to
>64 bit
>> >code. Besides, there are still some other issues:
>> >
>> >1). '-z max-page-size=0x1000' is used so the text segment start is
>in
>> >multiboot header search scope because GNU LD has default page size
>of
>> >0x00200000 for ELF64, which will fail multiboot test.
>> >
>> >2). The bootloader like grub has support for ELF kernel (even for
>ELF64)
>> >which makes the patch easier. However, the current grub
>implementaion thinks
>> >the entry address should be a VA. E.g. for 64 bit kernel, the entry
>address
>> >(0x1000000) is actually phiscial address, grub refuses to load it by
>saying:
>> >'entry point isn't in a segment'.
>> >
>> >This patch is sent out as RFC in case you have some ideas.
>> >
>> >Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
>> 
>> As has been shown many times before, this is a really bad idea. 
>Unless there
>> is a real-life use case where this matters enormously, this is nacked
>with
>> extreme prejudice.
>
>Just something to consider, provided the issues with multiboot get
>resolved:
>
>If you want to boot Xen you actually use the multiboot protocol, the
>last PVH
>boot patches had borrowed ideas from Multiboot to add an entry to
>Linux, only
>it was Xen'ified. What would be Multiboot 2 seemed flexible enough to
>allow all
>sorts of custom semantics and information stacked into a boot image.
>The last
>thought I had over this topic (before giving up)  was-- if we're going
>to add
>yet-another-entry (TM) why not add extend Mulitiboot 2 protocol with
>the
>semantics we need to boot any virtual environment and then add
>Multiboot 2
>support entry on Linux? We could redirect any custom boot mechanism
>then to
>just use that given its flexibility.
>
>  Luis

Multiboot has a fundamentally broken assumption, which is to do certain work for the kernel in the bootloader.  This is fundamentally a bad idea, because you always want to do things in the latest step possible during the boot process, being the most upgradeable, and have the interface as narrow as possible.

Therefore, using Multiboot is actively a negative step.  It is declared an "Open Standard" but anything can be such declared; it really is a claim that "everything should work like Grub."
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-15 20:58     ` hpa
@ 2017-02-16  2:07       ` Chao Peng
  2017-02-16 23:27       ` Daniel Kiper
  1 sibling, 0 replies; 10+ messages in thread
From: Chao Peng @ 2017-02-16  2:07 UTC (permalink / raw)
  To: hpa, Luis R. Rodriguez
  Cc: linux-kernel, x86, grub-devel, Thomas Gleixner, Ingo Molnar,
	Andy Lutomirski, Juergen Gross, Borislav Petkov, Josh Poimboeuf,
	Thomas Garnier, Al Viro, Michael S. Tsirkin, Paolo Bonzini,
	Amnon Ilan, Alexander Graf, Matt Fleming, Daniel Kiper


> > Just something to consider, provided the issues with multiboot get
> > resolved:
> > 
> > If you want to boot Xen you actually use the multiboot protocol, the
> > last PVH
> > boot patches had borrowed ideas from Multiboot to add an entry to
> > Linux, only
> > it was Xen'ified. What would be Multiboot 2 seemed flexible enough to
> > allow all
> > sorts of custom semantics and information stacked into a boot image.
> > The last
> > thought I had over this topic (before giving up)  was-- if we're going
> > to add
> > yet-another-entry (TM) why not add extend Mulitiboot 2 protocol with
> > the
> > semantics we need to boot any virtual environment and then add
> > Multiboot 2
> > support entry on Linux? We could redirect any custom boot mechanism
> > then to
> > just use that given its flexibility.
> > 
> >  Luis
> 
> Multiboot has a fundamentally broken assumption, which is to do certain work for the kernel in the
> bootloader.  This is fundamentally a bad idea, because you always want to do things in the latest
> step possible during the boot process, being the most upgradeable, and have the interface as
> narrow as possible.
> 
> Therefore, using Multiboot is actively a negative step.  It is declared an "Open Standard" but
> anything can be such declared; it really is a claim that "everything should work like Grub."

Thanks Peter and Luis for comments.

Chao

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-15 16:42 ` Paolo Bonzini
@ 2017-02-16  2:12   ` Chao Peng
  0 siblings, 0 replies; 10+ messages in thread
From: Chao Peng @ 2017-02-16  2:12 UTC (permalink / raw)
  To: Paolo Bonzini, linux-kernel, x86, grub-devel
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Andy Lutomirski,
	Juergen Gross, Luis R. Rodriguez, Borislav Petkov,
	Josh Poimboeuf, Thomas Garnier, Al Viro, Michael S. Tsirkin,
	Amnon Ilan

On Wed, 2017-02-15 at 17:42 +0100, Paolo Bonzini wrote:
> 
> On 15/02/2017 15:41, Chao Peng wrote:
> > 
> > Multiboot specification (http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.texi?h=mul
> > tiboot2)
> > is an open standard that provides kernels with a uniform way to be booted
> > by multiboot-compliant bootloaders (like grub).
> > 
> > This patch is trying to make Linux ELF kernel image to be a
> > multiboot-compliant OS so that it can be loaded by a multiboot-comliant
> > bootloader. The benefit is eliminating the maintainance for realmode and
> > decompression code and especially when the kernel is loaded in a virtual
> > machine, the reducing for these code can greatly cuts down the boot time.
> > 
> > However, the current version of multiboot spec doesn't support 64 bit
> > well so for 64 bit kernel we need stub code to jump from 32 bit code to
> > 64 bit code. Besides, there are still some other issues:
> >   1). '-z max-page-size=0x1000' is used so the text segment start is in
> >   multiboot header search scope because GNU LD has default page size of
> >   0x00200000 for ELF64, which will fail multiboot test.
> > 
> >   2). The bootloader like grub has support for ELF kernel (even for ELF64)
> >   which makes the patch easier. However, the current grub implementaion
> >   thinks the entry address should be a VA. E.g. for 64 bit kernel, the entry
> >   address (0x1000000) is actually phiscial address, grub refuses to load it
> >   by saying: 'entry point isn't in a segment'.
> 
> For kvm-unit-tests, we do "objcopy -O elf32-i386 dest.32bit dest.64bit"
> and pass the resulting 32bit ELF file to grub.
> 
> Out of curiosity, what happens if you pass the resulting multiboot file
> to QEMU's -kernel option?
> 

The resulting kernel is a multiboot2 kernel. QEMU however supports loading
multiboot v1 only.

Chao
> Thanks,
> 
> Paolo
> 
> > 
> > This patch is sent out as RFC in case you have some ideas.
> > 
> > Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-15 20:58     ` hpa
  2017-02-16  2:07       ` Chao Peng
@ 2017-02-16 23:27       ` Daniel Kiper
  2017-02-17  5:00         ` H. Peter Anvin
  1 sibling, 1 reply; 10+ messages in thread
From: Daniel Kiper @ 2017-02-16 23:27 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Luis R. Rodriguez, Juergen Gross, Paolo Bonzini,
	Michael S. Tsirkin, Matt Fleming, Daniel Kiper, x86,
	linux-kernel, Alexander Graf, Ingo Molnar, Al Viro,
	Andy Lutomirski, Josh Poimboeuf, Chao Peng, Thomas Gleixner,
	Borislav Petkov, Amnon Ilan, Thomas Garnier, hpa, phcoder,
	arvidjaar, konrad.wilk

On Wed, Feb 15, 2017 at 12:58:37PM -0800, hpa@zytor.com wrote:

[...]

> Multiboot has a fundamentally broken assumption, which is to do certain work

Just to be precise. We are talking about Multiboot2 here.

> for the kernel in the bootloader. This is fundamentally a bad idea, because

Why it is a bad idea? I think that it depends on a kernel. Some may wish to
figure out all/some machine details ourselves. However, some may do not care
and take everything from a bootloader. Anyway, Multiboot and Multiboot2 specs
do not force anybody to take one way or another. You are free to choose what
you like. Even more, you can pick exactly what you like.

> you always want to do things in the latest step possible during the boot process,

I can agree to some extent.

> being the most upgradeable,

Here I am not sure what you mean.

> and have the interface as narrow as possible.

That is obvious. Do you think that Multiboot/Multiboot2 protocols are
substantially suboptimal?

> Therefore, using Multiboot is actively a negative step.

Do you have better proposal? To be precise, I am not talking about patch itself
but about idea (of one common/standard boot protocol) in general.

> It is declared an "Open Standard" but anything can be such declared; it really
> is a claim that "everything should work like Grub."

I have not seen such statement in Multiboot and/or Multiboot2 spec. Of course it
was prepared by GRUB guys and the "reference" implementation is there. Though,
anybody may come and extend specs if he/she wishes. And I did it. Of course I can
agree that they are not perfect (especially Multiboot proto is very inflexible).
However, both protos try to standardize boot process. I think it is nice because
right now almost every (new) kernel has own boot protcol (some even support more
then one, sic!). And it is enormous task to support all of them in one boot loader.
So, I think that Multiboot protocols family (IMO, Multiboot2 is preferred today)
are good idea. Are they not perfect? Yes, but I do not think that proliferation
of tons of incompatible boot protocols, each specific for one kernel, is better.
So, if you think that we can fix something in Multiboot2 please tell us. If you
think that it is unfixable please tell us too. We can think about Multiboot3 too
(ehhh... maybe this is not the best idea). Anyway, it would be nice if one day
we have one common boot protocol for (almost) everybody.

Daniel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-16 23:27       ` Daniel Kiper
@ 2017-02-17  5:00         ` H. Peter Anvin
  2017-02-20 18:46           ` Daniel Kiper
  0 siblings, 1 reply; 10+ messages in thread
From: H. Peter Anvin @ 2017-02-17  5:00 UTC (permalink / raw)
  To: Daniel Kiper, The development of GNU GRUB
  Cc: Luis R. Rodriguez, Juergen Gross, Paolo Bonzini,
	Michael S. Tsirkin, Matt Fleming, Daniel Kiper, x86,
	linux-kernel, Alexander Graf, Ingo Molnar, Al Viro,
	Andy Lutomirski, Josh Poimboeuf, Chao Peng, Thomas Gleixner,
	Borislav Petkov, Amnon Ilan, Thomas Garnier, phcoder, arvidjaar,
	konrad.wilk

On 02/16/17 15:27, Daniel Kiper wrote:
> 
> That is obvious. Do you think that Multiboot/Multiboot2 protocols are
> substantially suboptimal?
> 

Yes.  They push a lot of things into the bootloader for no good reason,
thus tying the kernel's hands and making the whole boot process more
fragile.

It isn't either like Grub has been very good about keeping to any spec,
their own or others.

	-hpa

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able
  2017-02-17  5:00         ` H. Peter Anvin
@ 2017-02-20 18:46           ` Daniel Kiper
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Kiper @ 2017-02-20 18:46 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Daniel Kiper, Juergen Gross, Michael S. Tsirkin, Matt Fleming,
	phcoder, Daniel Kiper, x86, linux-kernel, Alexander Graf,
	arvidjaar, Luis R. Rodriguez, Ingo Molnar, Chao Peng, Al Viro,
	Andy Lutomirski, Josh Poimboeuf, Paolo Bonzini, Thomas Gleixner,
	Borislav Petkov, Amnon Ilan, Thomas Garnier, konrad.wilk

On Thu, Feb 16, 2017 at 09:00:05PM -0800, H. Peter Anvin wrote:
> On 02/16/17 15:27, Daniel Kiper wrote:
> > That is obvious. Do you think that Multiboot/Multiboot2 protocols are
> > substantially suboptimal?
>
> Yes.  They push a lot of things into the bootloader for no good reason,

I have not seen anything in Multiboot(2) specs which stipulates that every
bootloader must implement all features. If somebody needs minimal Multiboot(2)
compatible bootloader he/she can do that. Just parse Multiboot(2) header and
provide, let's call it in that way, empty boot data. Is it difficult?

> thus tying the kernel's hands and making the whole boot process more
> fragile.

Every kernel may take from the bootloader via Multiboot(2) what it needs.
No more no less. There is no requirement to use all data provided by
the bootloader.

> It isn't either like Grub has been very good about keeping to any spec,
> their own or others.

Could you be more precise?

Daniel

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-02-20 18:47 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-15 14:41 [RFC PATCH] x86/boot: make ELF kernel multiboot-able Chao Peng
2017-02-15 16:42 ` Paolo Bonzini
2017-02-16  2:12   ` Chao Peng
2017-02-15 18:12 ` hpa
2017-02-15 20:13   ` Luis R. Rodriguez
2017-02-15 20:58     ` hpa
2017-02-16  2:07       ` Chao Peng
2017-02-16 23:27       ` Daniel Kiper
2017-02-17  5:00         ` H. Peter Anvin
2017-02-20 18:46           ` Daniel Kiper

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.