first cut of ELF bzImage
Subsystems (2)
RFC PATCH 1/1 first cut of ELF bzImage
I started with Vivek's ELF bzImage patch from Oct last year, mashed it to apply to hpa's new setup/boot code.
This patch does a couple of things, which would probably be better split into multiple patches:
1. Glue an ELF header onto the front of bzImage. This is a real ELF header at the front of the file. Breaks akpm's laptop, apparently, but it works for me.
2. Drop tools/build, and use ld to do all the lifting to put the bzImage together. This has the advantage of being able to use the linker to compute all the things to shove in the ELF header and boot_params structure, rather than having to poke them in later.
3. Move notes out into their own .S. This is to make adding other notes (ie Xen) more obvious.
4. other random stuff (make linux/elf.h asm-includable)
Future stuff:
1. move the ELF header to a non-zero offset. Probably add a boot_param entry to point to it, but I suspect it will be within a few bytes of the start of the file (ie, just after the bugger-off jump)
2. actually try to load it as an elf file (though just running it as a command or under valgrind makes things, erm, upset)
3. other possibility hpa raised: make the compressed vmlinux payload an ELF file rather than the whole bzImage, and leave the bzImage wrapper as-is. seems sane to me.
What does everyone think? Is this heading in the right direction?
J
arch/i386/boot/Makefile +9 -14
@@ -29,8 +29,9 @@ subdir- := compressed subdir- := compressed setup-y += a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o -setup-y += header.o main.o mca.o memory.o pm.o pmjump.o +setup-y += header.o main.o mca.o memory.o notes.o pm.o pmjump.o setup-y += printf.o string.o tty.o video.o version.o voyager.o +setup-y += kernel.o # The link order of the video-*.o modules can matter. In particular, # video-vga.o *must* be listed first, followed by video-vesa.o.
@@ -39,10 +40,6 @@ setup-y += video-vga.o setup-y += video-vga.o setup-y += video-vesa.o setup-y += video-bios.o - -hostprogs-y := tools/build - -HOSTCFLAGS_build.o := $(LINUXINCLUDE) # ---------------------------------------------------------------------------
@@ -65,15 +62,10 @@ AFLAGS := $(CFLAGS) -D__ASSEMBLY__ $(obj)/bzImage: IMAGE_OFFSET := 0x100000 $(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__ $(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ -$(obj)/bzImage: BUILDFLAGS := -b -quiet_cmd_image = BUILD $@ -cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \ - $(obj)/vmlinux.bin $(ROOT_DEV) > $@ +all: $(obj)/bzImage -$(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \ - $(obj)/vmlinux.bin $(obj)/tools/build FORCE - $(call if_changed,image) +$(obj)/zImage: FORCE @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
@@ -81,8 +73,11 @@ cmd_image = $(obj)/tools/build $(BUILDFL SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) -LDFLAGS_setup.elf := -T -$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE +$(obj)/kernel.o: EXTRA_AFLAGS := -Wa,-I$(obj) +$(obj)/kernel.o: $(src)/kernel.S $(obj)/vmlinux.bin + +LDFLAGS_bzImage := -T +$(obj)/bzImage: $(src)/setup.ld $(SETUP_OBJS) FORCE $(call if_changed,ld) OBJCOPYFLAGS_setup.bin := -O binary
arch/i386/boot/header.S +69 -4
100 lines not on this page · raw message
arch/i386/boot/notes.S new file +8 -0
@@ -0,0 +1,8 @@ +#include <linux/elfnote.h> +#include <linux/elf_boot.h> +#include <linux/utsrelease.h> + +ELFNOTE(ELF_NOTE_BOOT, EIN_PROGRAM_NAME, .asciz "Linux") +ELFNOTE(ELF_NOTE_BOOT, EIN_PROGRAM_VERSION, .asciz UTS_RELEASE) +ELFNOTE(ELF_NOTE_BOOT, EIN_ARGUMENT_STYLE, .asciz "Linux") +ELFNOTE(ELF_NOTE_BOOT, EIN_BOOT_PARAMS, .long _start)
arch/i386/boot/setup.ld +23 -4
@@ -3,7 +3,7 @@ * * Linker script for the i386 setup code */ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_FORMAT("binary") OUTPUT_ARCH(i386) ENTRY(_start)
@@ -15,6 +15,7 @@ SECTIONS . = 497; .header : { *(.header) } + _text = .; .inittext : { *(.inittext) } .initdata : { *(.initdata) } .text : { *(.text*) }
@@ -36,6 +37,7 @@ SECTIONS LONG(0x5a5aaa55) } + _filesz = . - _text; . = ALIGN(16); __bss_start = .;
@@ -46,8 +48,25 @@ SECTIONS . = ALIGN(16); _end = .; - /DISCARD/ : { *(.note*) } + _memsz = . - _text; - . = ASSERT(_end <= 0x8000, "Setup too big!"); - . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); + __setup_sects = . / 512; + + _ = ASSERT(_end <= 0x8000, "Setup too big!"); + _ = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); + + .notes : { + notes = .; + *(.note*) + notes_end = .; + } + notes_size = notes_end - notes; + + .kernel : { + kernel = .; + *(.kernel) + kernel_end = .; + kernel_size = kernel_end - kernel; + kernel_size_para = (kernel_size + 15) / 16; + } }
arch/i386/boot/tools/.gitignore deleted +0 -1
@@ -1,1 +0,0 @@ -build
arch/i386/boot/tools/build.c deleted +0 -168
168 lines not on this page · raw message
include/linux/elf.h +16 -2
@@ -1,9 +1,10 @@#ifndef _LINUX_ELF_H#define _LINUX_ELF_H +#include <linux/elf-em.h> +#ifndef __ASSEMBLY__#include <linux/types.h> #include <linux/auxvec.h> -#include <linux/elf-em.h> #include <asm/elf.h> struct file ;
@@ -31,6 +32,7 @@ typedef __u32 Elf64_Word;typedef __u32 Elf64_Word ;typedef __u64 Elf64_Xword ;typedef __s64 Elf64_Sxword ; +#endif /* __ASSEMBLY__ */ /* These constants are for the segment types stored in the image headers */ #define PT_NULL 0
@@ -123,6 +125,7 @@ typedef __s64 Elf64_Sxword;#define ELF64_ST_BIND (x) ELF_ST_BIND(x)#define ELF64_ST_TYPE (x) ELF_ST_TYPE(x) +#ifndef __ASSEMBLY__ typedef struct dynamic{ Elf32_Sword d_tag; union{
@@ -138,6 +141,7 @@ typedef struct { Elf64_Addr d_ptr; } d_un; } Elf64_Dyn; +#endif /* __ASSEMBLY__ */ /* The following are used with relocations */ #define ELF32_R_SYM (x) ((x) >> 8)
@@ -146,6 +150,7 @@ typedef struct {#define ELF64_R_SYM (i) ((i) >> 32)#define ELF64_R_TYPE (i) ((i) & 0xffffffff) +#ifndef __ASSEMBLY__ typedef struct elf32_rel { Elf32_Addr r_offset; Elf32_Word r_info;
@@ -185,10 +190,11 @@ typedef struct elf64_sym {Elf64_Addr st_value;/* Value of the symbol */ Elf64_Xword st_size;/* Associated symbol size */ } Elf64_Sym; - +#endif /* __ASSEMBLY__ */ #define EI_NIDENT 16 +#ifndef __ASSEMBLY__ typedef struct elf32_hdr{ unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type;
@@ -222,6 +228,7 @@ typedef struct elf64_hdr {Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr; +#endif /* __ASSEMBLY__ */ /* These constants define the permissions on sections in the program header, p_flags. */
@@ -229,6 +236,7 @@ typedef struct elf64_hdr {#define PF_W 0x2#define PF_X 0x1 +#ifndef __ASSEMBLY__ typedef struct elf32_phdr{ Elf32_Word p_type; Elf32_Off p_offset;
@@ -250,6 +258,7 @@ typedef struct elf64_phdr {Elf64_Xword p_memsz;/* Segment size in memory */ Elf64_Xword p_align; /* Segment alignment, file & memory */ } Elf64_Phdr; +#endif /* __ASSEMBLY__ */ /* sh_type */ #define SHT_NULL 0
@@ -285,6 +294,7 @@ typedef struct elf64_phdr {#define SHN_COMMON 0xfff2#define SHN_HIRESERVE 0xffff +#ifndef __ASSEMBLY__ typedef struct elf32_shdr { Elf32_Word sh_name; Elf32_Word sh_type;
@@ -310,6 +320,7 @@ typedef struct elf64_shdr {Elf64_Xword sh_addralign;/* Section alignment */ Elf64_Xword sh_entsize; /* Entry size if section holds table */ } Elf64_Shdr; +#endif /* __ASSEMBLY__ */ #define EI_MAG0 0/* e_ident[] indexes */ #define EI_MAG1 1
@@ -343,6 +354,7 @@ typedef struct elf64_shdr {#define ELFOSABI_NONE 0#define ELFOSABI_LINUX 3 +#define ELFOSABI_STANDALONE 255#ifndef ELF_OSABI #define ELF_OSABI ELFOSABI_NONE
@@ -357,6 +369,7 @@ typedef struct elf64_shdr {#define NT_PRXFPREG 0x46e62b7f/* copied from gdb5.1/include/elf/common.h */ +#ifndef __ASSEMBLY__ /* Note header in a PT_NOTE section */ typedef struct elf32_note { Elf32_Word n_namesz; /* Name size */
@@ -396,5 +409,6 @@ static inline void arch_write_notes(stru#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size()#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)#endif /* ARCH_HAVE_EXTRA_ELF_NOTES */ +#endif /* __ASSEMBLY__ */ #endif /* _LINUX_ELF_H */
include/linux/elf_boot.h new file +16 -0
@@ -0,0 +1,16 @@ +#ifndef ELF_BOOT_H +#define ELF_BOOT_H + +/* Elf notes to help bootloaders identify what program they are booting. +*/ + +/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */ +#define ELF_NOTE_BOOT ELFBoot + +#define EIN_PROGRAM_NAME 1/* The program in this ELF file */ +#define EIN_PROGRAM_VERSION 2/* The version of the program in this ELF file */ +#define EIN_PROGRAM_CHECKSUM 3/* ip style checksum of the memory image. */ +#define EIN_ARGUMENT_STYLE 4/* String identifying argument passing style */ +#define EIN_BOOT_PARAMS 5/* Offset of boot_params block */ + +#endif /* ELF_BOOT_H */
The more I'm thinking about this whole issue, the more I'm thinking this is really misdirected.
I'm starting to think that the right thing to do might very well be as follows:
- Change the payload of the bzImage file from a flat binary to an ELF file -- a stripped vmlinux.gz.
- Change the decompressor to incorporate a (simple) ELF parser.
- Incorporate a couple of pointer fields in the bzImage header that points directly to the payload, the format of which can be identified via its magic number (currently gzip).
That way the environments that want to enter at the protected-mode entrypoint can do their own setup using whatever information is retained in the payload. Since most of these environments are currently using vmlinux as their boot file, this seems to make sense.
The more I hear about copying notes and various things from vmlinux to bzImage the more I'm convinced that this is a huge kluge. Furthermore, there are *definitely* virtual environments which would be much happier to be able to decompress in host space. The decompressor doesn't run well in many simulators.
-hpa
Quoted 6 lines · H. Peter Anvin
The more I'm thinking about this whole issue, the more I'm thinking this is really misdirected.
I'm starting to think that the right thing to do might very well be as follows:
Quoted 7 lines
- Change the payload of the bzImage file from a flat binary to an ELF file -- a stripped vmlinux.gz.
- Change the decompressor to incorporate a (simple) ELF parser.
- Incorporate a couple of pointer fields in the bzImage header that points directly to the payload, the format of which can be identified via its magic number (currently gzip).
I don't see a lot of benefit in doing this. Having some form of executable I can just run is probably simpler for me to implement than trying to unwrap a vmlinux.gz from an envelope, even if that's what we're currently booting. The Xen domain builder simply wants an ELF file it can load; if its a self-decompressing kernel image, then that's OK. The only real problem is setting up the initial mappings so that the booting code can run as if paging is enabled. The simplest answer to that is to simply 1:1 map all lowmem and set it running, but having specific Phdrs laying out the mappings would be a bit more refined.
Now if the bzImage were simply some 16-bit startup code prepended onto a self-decompressing 32-bit ELF kernel file, then that would be fairly easy to deal with too, since that would just be a matter of looking at the boot_params to find the start of the ELF file and continue from there.
Quoted 2 lines
The more I hear about copying notes and various things from vmlinux to bzImage the more I'm convinced that this is a huge kluge.
Copying notes? I don't think we'll need to do that. I'll put the Xen notes on the outermost envelope, but aside from that, there's no need to copy. It would definitely be useful to have ELF notes at the same level as the boot_params block, so that I can use one to find the other.
Quoted 4 lines
Furthermore,
there are *definitely* virtual environments which would be much happier to be able to decompress in host space. The decompressor doesn't run well in many simulators.
I'm not sure why you say that. Rusty managed to get unmodified bzImage's booting in lguest within a few hours of hacking. I don't expect Xen would be much different.
J
Quoted 9 lines · Jeremy Fitzhardinge
Quoted 4 lines · H. Peter Anvin
Furthermore,
there are *definitely* virtual environments which would be much happier to be able to decompress in host space. The decompressor doesn't run well in many simulators.I'm not sure why you say that. Rusty managed to get unmodified bzImage's booting in lguest within a few hours of hacking. I don't expect Xen would be much different.
Yes, it only required V=P mappings and skipping over the cli & segment reloads.
It's becoming pretty clear that booting with V=P mappings is in fact the right thing to do, so I don't think that's a real restriction. And we've discussed the cli and segment reloads already.
I understand the desire to restart from scratch, but I don't think we're there yet....
Rusty.
Quoted 24 lines · Jeremy Fitzhardinge
Quoted 6 lines · H. Peter Anvin
The more I'm thinking about this whole issue, the more I'm thinking this is really misdirected.
I'm starting to think that the right thing to do might very well be as follows:
Quoted 6 lines
- Change the payload of the bzImage file from a flat binary to an ELF file -- a stripped vmlinux.gz.
- Change the decompressor to incorporate a (simple) ELF parser.
- Incorporate a couple of pointer fields in the bzImage header that points directly to the payload, the format of which can be identified via its magic number (currently gzip).I don't see a lot of benefit in doing this. Having some form of executable I can just run is probably simpler for me to implement than trying to unwrap a vmlinux.gz from an envelope, even if that's what we're currently booting. The Xen domain builder simply wants an ELF file it can load; if its a self-decompressing kernel image, then that's OK. The only real problem is setting up the initial mappings so that the booting code can run as if paging is enabled. The simplest answer to that is to simply 1:1 map all lowmem and set it running, but having specific Phdrs laying out the mappings would be a bit more refined.
Quoted 5 lines
Now if the bzImage were simply some 16-bit startup code prepended onto a self-decompressing 32-bit ELF kernel file, then that would be fairly easy to deal with too, since that would just be a matter of looking at the
boot_paramsto find the start of the ELF file and continue from there.
You're focusing entirely on Xen here, but if Xen really is the only user of this, then I say there isn't much benefit into doing this at all. Hopefully we're trying to solve something bigger than the Xen domain builder being way too rigidly written, here.
So it really comes down to: what are the bigger problems we're solving?
Quoted 3 lines
I'm not sure why you say that. Rusty managed to get unmodified bzImage's booting in lguest within a few hours of hacking. I don't expect Xen would be much different.
Anything that's a true virtualizer should just be able to load and run a bzImage file from the 16-bit entrypoint, obviously. That's not what Rusty is doing, but all he'd need is the bit (already proposed) to inhibit cli and segment reloads.
-hpa
Quoted 31 lines · H. Peter Anvin
Quoted 24 lines · Jeremy Fitzhardinge
Quoted 6 lines · H. Peter Anvin
The more I'm thinking about this whole issue, the more I'm thinking this is really misdirected.
I'm starting to think that the right thing to do might very well be as follows:
Quoted 6 lines
- Change the payload of the bzImage file from a flat binary to an ELF file -- a stripped vmlinux.gz.
- Change the decompressor to incorporate a (simple) ELF parser.
- Incorporate a couple of pointer fields in the bzImage header that points directly to the payload, the format of which can be identified via its magic number (currently gzip).I don't see a lot of benefit in doing this. Having some form of executable I can just run is probably simpler for me to implement than trying to unwrap a vmlinux.gz from an envelope, even if that's what we're currently booting. The Xen domain builder simply wants an ELF file it can load; if its a self-decompressing kernel image, then that's OK. The only real problem is setting up the initial mappings so that the booting code can run as if paging is enabled. The simplest answer to that is to simply 1:1 map all lowmem and set it running, but having specific Phdrs laying out the mappings would be a bit more refined.
Quoted 5 lines
Now if the bzImage were simply some 16-bit startup code prepended onto a self-decompressing 32-bit ELF kernel file, then that would be fairly easy to deal with too, since that would just be a matter of looking at the
boot_paramsto find the start of the ELF file and continue from there.
Quoted 4 lines
You're focusing entirely on Xen here, but if Xen really is the only user of this, then I say there isn't much benefit into doing this at all. Hopefully we're trying to solve something bigger than the Xen domain builder being way too rigidly written, here.
We are. But it is honest to focus on the problems that you see. Jeremy I believe has already committed to changing the Xen domain builder.
I haven't seen much that Jeremy has been saying with respect to Xen that I haven't noted when working on /sbin/kexec.
However there is one more thing that is probably worth addressing. Having a bImage target where we do not compress the raw kernel binary. For embedded targets like OLPC they can actually store the kernel in less room by using a separate decompressor.
I don't think it would be very interesting to our traditional
Quoted 1 line
So it really comes down to: what are the bigger problems we're solving?
There are two basic core problems.
1) Cleaning starting a kernel in it's native mode. (32bit x86/64bit x86_64).
2) For bootloaders that boot a diverse set of standalone programs a minimal amount of code needed to support something different.
For kexec this is the cross architecture problem.
For things like Xen or Grub this is the multiple operating systems.
Keeping to a standard format helps here.
Reporting information about our selves that a standard query mechanism can use helps here.
I think we have seen this problems often enough it is worth solving things relatively cleanly.
Quoted 8 lines
Quoted 3 lines
I'm not sure why you say that. Rusty managed to get unmodified bzImage's booting in lguest within a few hours of hacking. I don't expect Xen would be much different.
Anything that's a true virtualizer should just be able to load and run a bzImage file from the 16-bit entrypoint, obviously. That's not what Rusty is doing, but all he'd need is the bit (already proposed) to inhibit cli and segment reloads.
The refined bit of more accurate headers reporting which memory the kernel can use before it runs may be nice, and in there.
Right now I suspect that changing the decompressor in the bzImage so that we are decompressing a vmlinux and then loading that could be a pain. At the moment we don't have code on the table for that.
Further if we manually roll our own headers and are not slaves to binutils we get a level of control that we might not have otherwise, and that we may need.
In particular we can set ET_DYN and set physical == virtual with no bad effects. binutils won't let us set ET_DYN on the program header when we are ``relocatable'' because it doesn't understand our what we are doing to make the kernel load time relocatable. We can't set physical == virtual on vmlinux or we would not be able to debug the loaded kernel. Setting physical == virtual in the bootloader context removes one area of ambiguity.
So we have 3 pieces to this puzzle.
- The linux boot parameters enhancement (I proposed some specific things that seemed essentially agreed upon).
In particular:
- A flag to say skip the cli and segment reload.
(We can just kill the cli (redundant) but things are just touchy
enough I'm not comfortable with unconditionally throwing out the segment reload code, and a flag that we set by default is cheap)
- A word to store the environment we are in.
- A pointer to environment specific data.
- ELF headers and ELF notes for general flexibility. I think this will take a little more discussion, but we are in essential agreement here.
- Where to put the ELF headers and ELF notes.
We have one patch on the table.
We have an alternative suggestion on the table.
The 16bit startup code at this point is modestly interesting, and I think we should have a standard way to find it so that bootloaders that want to use advanced features that can use
it have the option. However there is a very common intersection
between pc's without an x86 BIOS (so we can't run 16bit code) and bootloaders doing things differently.
Eric
Quoted 5 lines · Eric W. Biederman
Right now I suspect that changing the decompressor in the bzImage so that we are decompressing a vmlinux and then loading that could be a pain. At the moment we don't have code on the table for that.
Architecture comes before code. Just saying "well, we have code for X" is how you end up with a collected pile of crap. Sorry. Having said that, I recently enough wrote code to do this kind of stuff that I feel confident to say it's not hard.
Quoted 11 lines
Further if we manually roll our own headers and are not slaves to binutils we get a level of control that we might not have otherwise, and that we may need.
In particular we can set
ET_DYNand set physical == virtual with no bad effects. binutils won't let us setET_DYNon the program header when we are ``relocatable'' because it doesn't understand our what we are doing to make the kernel load time relocatable. We can't set physical == virtual on vmlinux or we would not be able to debug the loaded kernel. Setting physical == virtual in the bootloader context removes one area of ambiguity.
Now you're talking about how to implement the linker. I think that's a secondary issue.
Quoted 6 lines
The 16bit startup code at this point is modestly interesting, and I think we should have a standard way to find it so that bootloaders that want to use advanced features that can use
it have the option. However there is a very common intersection
between pc's without an x86 BIOS (so we can't run 16bit code) and bootloaders doing things differently.
Without any concept of what those "advanced features" are, we're just designing blind. The only "advanced feature" I can think of that would be applicable is relocation, and that one is already taken care of.
Quoted 7 lines
Quoted 4 lines
Anything that's a true virtualizer should just be able to load and run a
Quoted 3 lines
bzImage file from the 16-bit entrypoint, obviously. That's not what Rusty is doing, but all he'd need is the bit (already proposed) to inhibit cli and segment reloads.
The refined bit of more accurate headers reporting which memory the kernel can use before it runs may be nice, and in there.
"May be nice" is pretty darn weak. This all seems to come down to not really thinking through the various use cases and what the overarching architecture really needs to look like.
I personally suspect that the intersection of loaders that want to do protected-mode/long-mode entry and the ones that have any use of these "advanced features" you mention is, in fact, zero. At that point, it seems that what you really want is vmlinux.gz (whether or not it's produced by binutils is another matter entirely.) Users find it frustrating to have "the kernel" be different from situations that want vmlinux from the ones that want bzImage; what I'm suggesting is that they can have it both ways.
-hpa
Quoted 34 lines · H. Peter Anvin
Quoted 25 lines · Jeremy Fitzhardinge
Quoted 6 lines · H. Peter Anvin
The more I'm thinking about this whole issue, the more I'm thinking this is really misdirected.
I'm starting to think that the right thing to do might very well be as follows:
Quoted 7 lines
- Change the payload of the bzImage file from a flat binary to an ELF file -- a stripped vmlinux.gz.
- Change the decompressor to incorporate a (simple) ELF parser.
- Incorporate a couple of pointer fields in the bzImage header that points directly to the payload, the format of which can be identified via its magic number (currently gzip).I don't see a lot of benefit in doing this. Having some form of executable I can just run is probably simpler for me to implement than trying to unwrap a vmlinux.gz from an envelope, even if that's what we're currently booting. The Xen domain builder simply wants an ELF file it can load; if its a self-decompressing kernel image, then that's OK. The only real problem is setting up the initial mappings so that the booting code can run as if paging is enabled. The simplest answer to that is to simply 1:1 map all lowmem and set it running, but having specific Phdrs laying out the mappings would be a bit more refined.
Quoted 6 lines
Now if the bzImage were simply some 16-bit startup code prepended onto a self-decompressing 32-bit ELF kernel file, then that would be fairly easy to deal with too, since that would just be a matter of looking at the
boot_paramsto find the start of the ELF file and continue from there.
Quoted 3 lines
You're focusing entirely on Xen here, but if Xen really is the only user of this, then I say there isn't much benefit into doing this at all.
No, I'm using Xen as a concrete example of something which already exists with well-understood requirements. I don't think its requirements are so wacky that it's unrepresentative of other things which may want to use the same mechanism. It's much better to talk about concrete examples rather than just wave an "architecture-in-the-abstract" wand around.
Quoted 2 lines
So it really comes down to: what are the bigger problems we're solving?
I think the concise statement is: how do we boot a kernel in 32/64-bit mode, bypassing as much cruft as possible while supporting the widest possible range of environments?
I think the environment space can be broadly parameterised by:
paging enabled: yes(pae)/yes(non-pae)/no
running in ring: 0/1/3
mode: paravirtualized/native
Quoted 5 lines
Anything that's a true virtualizer should just be able to load and run a bzImage file from the 16-bit entrypoint, obviously. That's not what Rusty is doing, but all he'd need is the bit (already proposed) to inhibit cli and segment reloads.
Yes, well, we're not talking about full virtualization. If we were then there'd be nothing to talk about.
Avoiding cli and segment reloads are part of the general "running paravirtualized" (or perhaps "running in non-ring 0") part of the environment space, which is common to all the current paravirt implementations (though I think vmi and kvm will both be running fully virtualized at the point in the boot).
J
Quoted 46 lines · Eric W. Biederman
Quoted 33 lines · H. Peter Anvin
Quoted 25 lines · Jeremy Fitzhardinge
Quoted 6 lines · H. Peter Anvin
The more I'm thinking about this whole issue, the more I'm thinking this is really misdirected.
I'm starting to think that the right thing to do might very well be as follows:
Quoted 7 lines
- Change the payload of the bzImage file from a flat binary to an ELF file -- a stripped vmlinux.gz.
- Change the decompressor to incorporate a (simple) ELF parser.
- Incorporate a couple of pointer fields in the bzImage header that points directly to the payload, the format of which can be identified via its magic number (currently gzip).I don't see a lot of benefit in doing this. Having some form of executable I can just run is probably simpler for me to implement than trying to unwrap a vmlinux.gz from an envelope, even if that's what we're currently booting. The Xen domain builder simply wants an ELF file it can load; if its a self-decompressing kernel image, then that's OK. The only real problem is setting up the initial mappings so that the booting code can run as if paging is enabled. The simplest answer to that is to simply 1:1 map all lowmem and set it running, but having specific Phdrs laying out the mappings would be a bit more refined.
Quoted 6 lines
Now if the bzImage were simply some 16-bit startup code prepended onto a self-decompressing 32-bit ELF kernel file, then that would be fairly easy to deal with too, since that would just be a matter of looking at the
boot_paramsto find the start of the ELF file and continue from there.Quoted 5 lines
You're focusing entirely on Xen here, but if Xen really is the only user of this, then I say there isn't much benefit into doing this at all. Hopefully we're trying to solve something bigger than the Xen domain builder being way too rigidly written, here.
We are. But it is honest to focus on the problems that you see. Jeremy I believe has already committed to changing the Xen domain builder.
Quoted 8 lines
I haven't seen much that Jeremy has been saying with respect to Xen that I haven't noted when working on
/sbin/kexec.However there is one more thing that is probably worth addressing. Having a bImage target where we do not compress the raw kernel binary. For embedded targets like OLPC they can actually store the kernel in less room by using a separate decompressor.
Well, I think that comes pretty naturally if we treat bzImage = 16-bit startup + ELF kernel image,
where the ELF file can either be a whole vmlinux, or a self-decompressing kernel.
Quoted 2 lines
I don't think it would be very interesting to our traditional
...? Uncompressed kernel not interesting to existing/traditional boot environments?
Quoted 11 lines
Quoted 2 lines
So it really comes down to: what are the bigger problems we're solving?
There are two basic core problems.
1) Cleaning starting a kernel in it's native mode. (32bit x86/64bitx86_64).
2) For bootloaders that boot a diverse set of standalone programs a minimal amount of code needed to support something different.For kexec this is the cross architecture problem.
For things like Xen or Grub this is the multiple operating systems.
Quoted 7 lines
Keeping to a standard format helps here.
Reporting information about our selves that a standard query mechanism can use helps here.I think we have seen this problems often enough it is worth solving things relatively cleanly.
Also there seem to be enough current diverse users of this mechanism that any design we come up with to satisfy existing requirements will likely be a good start for any future users (ie, it may work as-is, or failing that it should be relatively extensible, so long as we manage to not introduce some unfortunate limitation).
Quoted 11 lines
The refined bit of more accurate headers reporting which memory the kernel can use before it runs may be nice, and in there.
Right now I suspect that changing the decompressor in the bzImage so that we are decompressing a vmlinux and then loading that could be a pain. At the moment we don't have code on the table for that.
Further if we manually roll our own headers and are not slaves to binutils we get a level of control that we might not have otherwise, and that we may need.
Well, that's orthogonal. So long as we don't get carried away, its not too hard to arrange to get ld to do all the heavy lifting, while letting us use gas to generate finely tuned ELF headers. We can use the same technique for both bzImage and/or the kernel image itself.
Quoted 9 lines
So we have 3 pieces to this puzzle.
- The linux boot parameters enhancement (I proposed some specific things that seemed essentially agreed upon).
In particular:
- A flag to say skip the cli and segment reload.
(We can just kill the cli (redundant) but things are just touchy
enough I'm not comfortable with unconditionally throwing out the segment reload code, and a flag that we set by default is cheap)
(So long as segment reload includes a gdt reload.)
J
Quoted 4 lines · H. Peter Anvin
Without any concept of what those "advanced features" are, we're just designing blind. The only "advanced feature" I can think of that would be applicable is relocation, and that one is already taken care of.
Well, I'm not sure what "advanced" really encompasses, but it seems to me it would also include:
* relocation
* booting in protected mode
* booting with paging enabled, which allows
* physically discontigious kernels
* ...?
J