aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/boot
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-02-03 18:11:03 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-02-03 18:11:03 +0000
commit964fb3d6365b7d3b582b895e2473446f814787d0 (patch)
treeee71b51e890b502a321e9bdc3bbcaba90da90de0 /xen/arch/x86/boot
parent684e6b10cb1dd75ba736576204bc25b945e87850 (diff)
downloadxen-964fb3d6365b7d3b582b895e2473446f814787d0.tar.gz
xen-964fb3d6365b7d3b582b895e2473446f814787d0.tar.bz2
xen-964fb3d6365b7d3b582b895e2473446f814787d0.zip
x86: Relocate Multiboot structures where we know they will be
accessible. GRUB2 seems to like to stick them really high sometimes (just below 4GB). The 32-bit C code framework that this sets up can also be used for other stuff in future: * early cmdline parsing * relocating multiboot modules so they too are guaranteed accessible Its interaction with normal Xen start-of-day, and with the 16-bit assembly trampoline, needs a bit of thought. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/arch/x86/boot')
-rw-r--r--xen/arch/x86/boot/Makefile6
-rw-r--r--xen/arch/x86/boot/build32.mk24
-rw-r--r--xen/arch/x86/boot/head.S10
-rw-r--r--xen/arch/x86/boot/reloc.c80
4 files changed, 118 insertions, 2 deletions
diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile
index 3340058c08..d9a7c3f963 100644
--- a/xen/arch/x86/boot/Makefile
+++ b/xen/arch/x86/boot/Makefile
@@ -1 +1,7 @@
obj-y += head.o
+
+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 0000000000..3223bcf4f9
--- /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 c10aa62b2d..3360107aac 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 0000000000..d0ae7dc9fc
--- /dev/null
+++ b/xen/arch/x86/boot/reloc.c
@@ -0,0 +1,80 @@
+/******************************************************************************
+ * 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 <keir.fraser@citrix.com>
+ */
+
+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);
+}
+
+multiboot_info_t *reloc(multiboot_info_t *mbi_old)
+{
+ multiboot_info_t *mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi));
+
+ if ( mbi->flags & MBI_CMDLINE )
+ {
+ char *cmdline_old, *p;
+ cmdline_old = (char *)mbi->cmdline;
+ for ( p = cmdline_old; *p != '\0'; p++ )
+ continue;
+ mbi->cmdline = (u32)reloc_mbi_struct(cmdline_old, p - cmdline_old + 1);
+ }
+
+ if ( mbi->flags & MBI_MODULES )
+ mbi->mods_addr = (u32)reloc_mbi_struct(
+ (module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t));
+
+ 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;
+}