x86 boot enhancements, footprint rediction 7/11
PATCH 1/1 x86 boot enhancements, footprint rediction 7/11
Linus please apply,
Solve the space/reliability tradeoff misc.c asks bootloaders to make, with belt and suspenders.
- modify misc.c to relocate the real mode code to maximize low memory usage.
- modify misc.c to do inplace decompression
- modify setup.S to query int12 to get the low memory size
- Introduce STAY_PUT flag for bootloaders that don't pass a command_line but still don't need the bootsector to relocate itself.
The kernel now uses approximately 78KB of memory below 1MB and 8 bytes more than the decompressesed kernel above 1MB. And if required everything except the 5KB of real mode code can go above 1MB.
The 78KB below 1MB is 5KB real mode code 10KB decompressor code 61KB bss.
The change is especially nice because now in my worst case of only using 5KB real mode data, I do better than the best case with previous kernels (assuming it isn't a zImage). And if I ever get the bootmem bootmap fixed I can put initrds down at 2.6MB and not have to worry about them getting stomped :)
Eric
arch/i386/boot/compressed/Makefile +3 -5
@@ -9,8 +9,6 @@ OBJECTS = $(HEAD) misc.o -ZLDFLAGS = -e startup_32 - # # ZIMAGE_OFFSET is the load offset of the compression loader # BZIMAGE_OFFSET is the load offset of the high loaded compression loader
@@ -18,8 +16,8 @@ ZIMAGE_OFFSET = 0x1000 BZIMAGE_OFFSET = 0x100000 -ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS) -BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS) +ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) -T vmlinuz.lds +BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) -T vmlinuz.lds all: vmlinux
@@ -42,7 +40,7 @@ rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \ $(OBJCOPY) $(SYSTEM) $$tmppiggy; \ gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \ - echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \ + echo "SECTIONS { .input : { *(.data) }}" > $$tmppiggy.lnk; \ $(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-i386 -T $$tmppiggy.lnk; \ rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk
arch/i386/boot/compressed/head.S +26 -0
@@ -30,6 +30,20 @@ .globl startup_32 startup_32: + jmp 1f + .balign 4 + .globl input_addr, input_len, output_overhang + .globl kernel_base, kernel_memsz, kernel_filesz + .globl unzip_memsz, unzip_filesz +input_addr: .long input_data +input_len: .long input_data_len +output_overhang: .long input_data_len # Will be set to 8 later... +kernel_base: .long HIGH_BASE +kernel_memsz: .long 0 +kernel_filesz: .long 0 +unzip_memsz: .long _end +unzip_filesz: .long _edata +1: cld cli
@@ -44,6 +58,18 @@ movl %edi, edi movl %esp, esp movl %ebp, ebp + + /* + * Move the input data off the bss segment + */ + std + movl $input_data_end -1, %esi + movl %esi, %edi + addl $input_data_shift, %edi + movl $input_data_len, %ecx + rep movsb + cld + addl $input_data_shift, input_addr /* * Setup the stack
arch/i386/boot/compressed/misc.c +123 -65
288 lines not on this page · raw message
arch/i386/boot/compressed/vmlinuz.lds +29 -0
@@ -0,0 +1,29 @@ +/* ld script to make compressed i386 Linux kernel + */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(startup_32) +SECTIONS +{ + . = 0x1000; + _text = .; /* Text and read-only data */ + .text : { *(.text) } = 0x9090 + _etext = .; /* End of text section */ + .rodata : { *(.rodata) *(.rodata.*) } + .data : { + *(.data) + + } + _edata = .; /* End of data section */ + .bss _edata : { *(.bss) } + _end = .; + .input _edata : { + input_data = . ; + *(.input) + input_data_end = . ; + } + input_data_len = input_data_end - input_data; + input_data_shift = _end - _edata; + + /DISCARD/ : { *(*) } +}
arch/i386/boot/setup.S +21 -4
@@ -106,6 +106,8 @@ # flags, unused bits must be zero (RFU) bit within loadflags loadflags: LOADED_HIGH = 1 # If set, the kernel is loaded high +STAY_PUT = 0x40 # If set, the loader doesn't expect + # us to relocate anything CAN_USE_HEAP = 0x80 # If set, the loader also has set # heap_end_ptr to tell how much # space behind setup.S can be used for
@@ -162,7 +164,11 @@ # The highest safe address for # the contents of an initrd -# variables private to setup.S (not for bootloaders) +# variables private to the kernel (not for bootloaders) +pad2: .long 0 +real_base: .long REAL_BASE # Location of real mode kernel +real_memsz: # Memory usage of real mode kernel + .long (_esetup_heap - _setup) + DELTA_BOOTSECT real_filesz: # Datasize of the real mode kernel .long (_esetup - _setup) + DELTA_BOOTSECT trampoline: call start_of_setup
@@ -297,6 +303,15 @@ #endif /* __BIG_KERNEL__ */ loader_ok: +# Get base memory size +# The size in kilobytes is returned in %ax +# There shouldn't be any subfunctions but just +# in case we clear eax and ecx + xorl %eax, %eax + xorl %ecx, %ecx + int $0x12 + movw %ax, (0x1e4) + # Get memory size (extended mem, kB) xorl %eax, %eax
@@ -604,12 +619,13 @@ # then we load the segment descriptors movw %cs, %ax # aka SETUPSEG movw %ax, %ds - + # Check whether we need to be downward compatible with version <=201 +# We don't relocate if STAY_PUT is specified or we have a 202 cmd_line + testb $STAY_PUT, loadflags + jnz end_move_self cmpl $0, cmd_line_ptr jne end_move_self # loader uses version >=202 features - cmpb $0x20, type_of_loader - je end_move_self # bootsect loader, we know of it # Boot loader doesnt support boot protocol version 2.02. # If we have our code not at 0x90000, we need to move it there now.
@@ -846,6 +862,7 @@ jnz bootsect_second movb $0x20, %cs:type_of_loader + orb $STAY_PUT, %cs:loadflags movw %es, %ax shrw $4, %ax movb %ah, %cs:bootsect_src_base+2
arch/i386/boot/tools/build.c +157 -6
191 lines not on this page · raw message
include/asm-i386/boot_param.h +7 -3
@@ -37,7 +37,8 @@struct drive_info_struct drive_info;/* 0x80 */ struct sys_desc_table sys_desc_table;/* 0xa0 */ __u32 alt_mem_k;/* 0x1e0 */ -__u8 reserved5[4 ];/* 0x1e4 */ +__u16 base_mem_k;/* 0x1e4 */ +__u8 reserved5[2 ];/* 0x1e6 */ __u8 e820_map_nr;/* 0x1e8 */ __u8 reserved6[8 ];/* 0x1e9 */ __u8 setup_sects;/* 0x1f1 */
@@ -83,8 +84,11 @@/* 2.03+ */ __u32 ramdisk_max;/* 0x22c */ /* Below this point for internal kernel use only */ -__u32 real_filesz;/* 0x230 */ -__u8 reserved15[0x2d0 -0x234 ];/* 0x234 */ +__u32 pad2;/* 0x230 */ +__u32 real_base;/* 0x234 */ +__u32 real_memsz;/* 0x238 */ +__u32 real_filesz;/* 0x23c */ +__u8 reserved15[0x2d0 -0x240 ];/* 0x240 */ struct e820entry e820_map[E820MAX ];/* 0x2d0 */ /* 0x550 */ } __attribute__((packed));