From: Ross Philipson Date: Wed, 4 Feb 2009 19:13:30 +0000 (-0500) Subject: Changes to boot code to relocate the MBI. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=07c5567f77954a3a3e8def00a766c428c78b0e6f;p=xenclient%2Fxen.git Changes to boot code to relocate the MBI. This fix relocates the MBI and associated data to safe memory locations before paging is enabled. This fixes the issue with GRUB2 loading chunks of the MBI at very high phys. addresses. These fixes are from xen-unstable change- sets 19146 and 19158. Changes to be committed: (use "git reset HEAD ..." to unstage) modified: xen/arch/x86/Makefile modified: xen/arch/x86/boot/Makefile new file: xen/arch/x86/boot/build32.mk modified: xen/arch/x86/boot/head.S new file: xen/arch/x86/boot/reloc.c --- diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index eb9dd08..b2930ff 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -91,3 +91,4 @@ boot/mkelf32: boot/mkelf32.c clean:: rm -f asm-offsets.s xen.lds boot/*.o boot/*~ boot/core boot/mkelf32 rm -f $(BASEDIR)/.xen-syms.[0-9]* + rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index ce5c935..d9a7c3f 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -1,4 +1,7 @@ obj-y += head.o -head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S \ - cmdline.S edd.S wakeup.S +head.o: reloc.S + +# NB. BOOT_TRAMPOLINE == 0x8c000 +%.S: %.c + RELOC=0x8c000 $(MAKE) -f build32.mk $@ diff --git a/xen/arch/x86/boot/build32.mk b/xen/arch/x86/boot/build32.mk new file mode 100644 index 0000000..3223bcf --- /dev/null +++ b/xen/arch/x86/boot/build32.mk @@ -0,0 +1,24 @@ +XEN_ROOT=../../../.. +override XEN_TARGET_ARCH=x86_32 +CFLAGS = +include $(XEN_ROOT)/Config.mk + +# Disable PIE/SSP if GCC supports them. They can break us. +$(call cc-option-add,CFLAGS,CC,-nopie) +$(call cc-option-add,CFLAGS,CC,-fno-stack-protector) +$(call cc-option-add,CFLAGS,CC,-fno-stack-protector-all) + +CFLAGS += -Werror -fno-builtin -msoft-float + +%.S: %.bin + (od -v -t x $< | head -n -1 | \ + sed 's/ /,0x/g' | sed 's/^[0-9]*,/ .long /') >$@ + +%.bin: %.lnk + $(OBJCOPY) -O binary $< $@ + +%.lnk: %.o + $(LD) $(LDFLAGS_DIRECT) -N -Ttext 0x8c000 -o $@ $< + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index c10aa62..3360107 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -79,8 +79,11 @@ __start: cmp $0x2BADB002,%eax jne not_multiboot - /* Save the Multiboot info structure for later use. */ - mov %ebx,sym_phys(multiboot_ptr) + /* Save the Multiboot info struct (after relocation) for later use. */ + mov $sym_phys(cpu0_stack)+1024,%esp + push %ebx + call reloc + mov %eax,sym_phys(multiboot_ptr) /* Initialize BSS (no nasty surprises!) */ mov $sym_phys(__bss_start),%edi @@ -192,6 +195,9 @@ __start: #include "cmdline.S" +reloc: +#include "reloc.S" + .align 16 .globl trampoline_start, trampoline_end trampoline_start: diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c new file mode 100644 index 0000000..e3333d3 --- /dev/null +++ b/xen/arch/x86/boot/reloc.c @@ -0,0 +1,89 @@ +/****************************************************************************** + * reloc.c + * + * 32-bit flat memory-map routines for relocating Multiboot structures + * and modules. This is most easily done early with paging disabled. + * + * Copyright (c) 2009, Citrix Systems, Inc. + * + * Authors: + * Keir Fraser + */ + +asm ( + " .text \n" + " .globl _start \n" + "_start: \n" + " mov $_start,%edi \n" + " call 1f \n" + "1: pop %esi \n" + " sub $1b-_start,%esi \n" + " mov $__bss_start-_start,%ecx \n" + " rep movsb \n" + " xor %eax,%eax \n" + " mov $_end,%ecx \n" + " sub %edi,%ecx \n" + " rep stosb \n" + " mov $reloc,%eax \n" + " jmp *%eax \n" + ); + +typedef unsigned int u32; +#include "../../../include/xen/multiboot.h" + +extern char _start[]; + +static void *memcpy(void *dest, const void *src, unsigned int n) +{ + char *s = (char *)src, *d = dest; + while ( n-- ) + *d++ = *s++; + return dest; +} + +static void *reloc_mbi_struct(void *old, unsigned int bytes) +{ + static void *alloc = &_start; + alloc = (void *)(((unsigned long)alloc - bytes) & ~15ul); + return memcpy(alloc, old, bytes); +} + +static char *reloc_mbi_string(char *old) +{ + char *p; + for ( p = old; *p != '\0'; p++ ) + continue; + return reloc_mbi_struct(old, p - old + 1); +} + +multiboot_info_t *reloc(multiboot_info_t *mbi_old) +{ + multiboot_info_t *mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi)); + int i; + + if ( mbi->flags & MBI_CMDLINE ) + mbi->cmdline = (u32)reloc_mbi_string((char *)mbi->cmdline); + + if ( mbi->flags & MBI_MODULES ) + { + module_t *mods = reloc_mbi_struct( + (module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t)); + mbi->mods_addr = (u32)mods; + for ( i = 0; i < mbi->mods_count; i++ ) + if ( mods[i].string ) + mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string); + } + + if ( mbi->flags & MBI_MEMMAP ) + mbi->mmap_addr = (u32)reloc_mbi_struct( + (memory_map_t *)mbi->mmap_addr, mbi->mmap_length); + + /* Mask features we don't understand or don't relocate. */ + mbi->flags &= (MBI_MEMLIMITS | + MBI_DRIVES | + MBI_CMDLINE | + MBI_MODULES | + MBI_MEMMAP); + + return mbi; +}