[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] RE: [Xen-devel] RFC/Patch: Support for other bootloaders
Here's a revised patch. I've eliminated support for trying to combine two modules into one loadable image. As per previous discussions, I think in these circumstances if a ramdisk is required it is adequate for it to be built-in to the dom0 image (e.g. embedded initramfs). Also included the agreed-upon cmdline hack, and SMP booting has been verified and fixed. (Not "signed-off" because I don't think it is ready just yet.) -- Michal Ostrowski <mostrows@xxxxxxxxxxxxxx> # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/24 09:19:31-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx # Support for non-grub boot-loaders. # # BitKeeper/etc/logging_ok # 2005/03/24 09:19:31-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +1 -0 # Logging to logging@xxxxxxxxxxxxxxx accepted # # xen/arch/x86/mkzen # 2005/03/24 09:19:28-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +76 -0 # # xen/include/xen/multiboot.h # 2005/03/24 09:19:28-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +4 -0 # Define reasonable max number of modules. # # xen/arch/x86/mkzen # 2005/03/24 09:19:28-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +0 -0 # BitKeeper file /home/mostrows/xen/xen.base/xen/arch/x86/mkzen # # xen/include/xen/lib.h # 2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +2 -1 # Return pointer to unparse portion of command line. # Stop parsing command line at "--". # # xen/common/kernel.c # 2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +9 -2 # Return pointer to unparse portion of command line. # Stop parsing command line at "--". # # xen/arch/x86/setup.c # 2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +166 -52 # Handle Linux-style boot-params structure if multi-boot headers not present. # # xen/arch/x86/boot/x86_32.S # 2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +13 -7 # Detect Linux-style boot-params in %ebx if no multi-boot magic number present. # # xen/arch/x86/Makefile # 2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +42 -0 # Add rules to build a zenImg (which incorporates Linux bzImage binaries). # Depends on LINUX_BUILD being defined to point to a linux build tree. # diff -Nru a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile 2005-03-24 09:20:15 -05:00 +++ b/xen/arch/x86/Makefile 2005-03-24 09:20:15 -05:00 @@ -15,7 +15,11 @@ OBJS := $(patsubst cdb%.o,,$(OBJS)) endif +ifdef LINUX_BUILD +default: $(TARGET) zenImg +else default: $(TARGET) +endif $(TARGET): $(TARGET)-syms boot/mkelf32 ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 @@ -32,6 +36,44 @@ boot/mkelf32: boot/mkelf32.c $(HOSTCC) $(HOSTCFLAGS) -o $@ $< + + +ifdef LINUX_BUILD + +# +# Check Makefile in Linux build dir. If it contains KERNELSRC, then use +# that as source dir, otherwise build==source dir +LINUX_SRC:= $(shell if grep -q KERNELSRC $(LINUX_BUILD)/Makefile ; then \ + sed -e '/^KERNELSRC/!d' $(LINUX_BUILD)/Makefile | \ + bash -c '( read A B C ; echo -n $$C)' ; \ + else \ + echo -n $(LINUX_BUILD); \ + fi ) + +$(TARGET).bin: $(TARGET) + $(OBJCOPY) -O binary -R .note -R .comment -S $^ $@ + +$(TARGET).bin.gz: $(TARGET).bin + gzip -f -9 < $< > $@ + +piggy.o: $(TARGET).bin.gz + $(LD) -m elf_i386 -r --format binary --oformat elf32-i386 \ + -T $(LINUX_SRC)/arch/i386/boot/compressed/vmlinux.scr $< -o $@ + +zen: $(LINUX_BUILD)/arch/i386/boot/compressed/head.o \ + $(LINUX_BUILD)/arch/i386/boot/compressed/misc.o \ + piggy.o + $(LD) -m elf_i386 -Ttext 0x100000 -e startup_32 $^ -o $@ + +zenImg: zen + $(OBJCOPY) -O binary -R .note -R .comment -S $^ $@.tmp + $(LINUX_BUILD)/arch/i386/boot/tools/build \ + -b $(LINUX_BUILD)/arch/i386/boot/bootsect \ + $(LINUX_BUILD)/arch/i386/boot/setup $@.tmp > $@ + + +endif + clean: rm -f *.o *.s *~ core boot/*.o boot/*~ boot/core boot/mkelf32 diff -Nru a/xen/arch/x86/boot/x86_32.S b/xen/arch/x86/boot/x86_32.S --- a/xen/arch/x86/boot/x86_32.S 2005-03-24 09:20:15 -05:00 +++ b/xen/arch/x86/boot/x86_32.S 2005-03-24 09:20:15 -05:00 @@ -55,7 +55,7 @@ mov %ecx,%gs ljmp $(__HYPERVISOR_CS),$(1f)-__PAGE_OFFSET 1: lss stack_start-__PAGE_OFFSET,%esp - + /* Reset EFLAGS (subsumes CLI and CLD). */ pushl $0 popf @@ -82,15 +82,21 @@ and $0x7f,%cl # CR4.PGE (global enable) mov %ecx,%cr4 - cmp $(SECONDARY_CPU_FLAG),%ebx - je start_paging - /* Check for Multiboot bootloader */ cmp $0x2BADB002,%eax - jne not_multiboot + je 1f - /* Save the Multiboot info structure for later use. */ - add $__PAGE_OFFSET,%ebx + /* No multi-boot? Hope that we've got a Linux boot-params */ + /* stashed in esi. Save in %ebx until stack is ready. */ + /* But do this only if this isn't a secondary cpu. */ + cmp $(SECONDARY_CPU_FLAG),%ebx + je 1f + movl %esi, %ebx +1: + cmp $(SECONDARY_CPU_FLAG),%ebx + je start_paging + + /* Stack is now ready, so store boot parameter pointer */ push %ebx /* Initialize BSS (no nasty surprises!) */ diff -Nru a/xen/arch/x86/mkzen b/xen/arch/x86/mkzen --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/xen/arch/x86/mkzen 2005-03-24 09:20:15 -05:00 @@ -0,0 +1,76 @@ +#!/bin/bash +# +# Copyright (C) 2005 Michal Ostrowski <mostrows@xxxxxxxxxxxxxx>, +# IBM Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + + +# Reaches into a Linux build tree and uses objects and scripts from +# linux to wrap a Xen ELF image in the Linuz bzImage machinery, +# allowing the resulting "zen" image to be booted using any +# boot-loader thant can load a Linux bzImage. + +# +# Usage: mkzen <LINUX_BUILD> <XEN IMAGE> <ZEN> + +set -e +LINUX_BUILD=$1 +XEN=$2 +ZEN=$3 + +: ${CROSS_COMPILE:=} +: ${OBJCOPY:=${CROSS_COMPILE}objcopy} +: ${LD:=${CROSS_COMPILE}ld} + +function cleanup(){ + rm -f ${XEN}.bin.$$ ${XEN}.bin.gz.$$ ${XEN}.piggy.o.$$ + rm -f ${ZEN}.1.$$ ${ZEN}.2.$$ +} + +trap cleanup ERR + +# +# Check Makefile in Linux build dir. If it contains KERNELSRC, then use +# that as source dir, otherwise build==source dir +# +LINUX_SRC=`sed -e '/^KERNELSRC/!d;s/^.*:=[ ]*//' < ${LINUX_BUILD}/Makefile` +if [ -z "${LINUX_SRC}" ]; then + LINUX_SRC=${LINUX_BUILD}; +fi + +${OBJCOPY} -O binary -R .note -R .comment -S ${XEN} ${XEN}.bin.$$ + +gzip -f -9 < ${XEN}.bin.$$ > ${XEN}.bin.gz.$$ + +${LD} -m elf_i386 -r --format binary --oformat elf32-i386 \ + -T ${LINUX_SRC}/arch/i386/boot/compressed/vmlinux.scr \ + ${XEN}.bin.gz -o ${XEN}.piggy.o.$$ + + +${LD} -m elf_i386 -Ttext 0x100000 -e startup_32 \ + ${LINUX_BUILD}/arch/i386/boot/compressed/head.o \ + ${LINUX_BUILD}/arch/i386/boot/compressed/misc.o ${XEN}.piggy.o.$$ \ + -o ${ZEN}.1.$$ + +${OBJCOPY} -O binary -R .note -R .comment -S ${ZEN}.1.$$ ${ZEN}.2.$$ + +${LINUX_BUILD}/arch/i386/boot/tools/build \ + -b ${LINUX_BUILD}/arch/i386/boot/bootsect \ + ${LINUX_BUILD}/arch/i386/boot/setup ${ZEN}.2.$$ > ${ZEN} + + +cleanup \ No newline at end of file diff -Nru a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c 2005-03-24 09:20:15 -05:00 +++ b/xen/arch/x86/setup.c 2005-03-24 09:20:15 -05:00 @@ -86,6 +86,22 @@ int phys_proc_id[NR_CPUS]; int logical_proc_id[NR_CPUS]; + +/* Details about what is found where in the Linux boot parameters area. */ +/* Put into a seperate header if it grows much more. */ +#define PARAM_SIZE 2048 +#define COMMAND_LINE_SIZE 256 +#define NEW_CL_POINTER 0x228 +#define E820NR 0x1e8 +#define E820MAP 0x2d0 +#define INITRD_START 0x218 +#define INITRD_SIZE 0x21c + +static unsigned char boot_params[PARAM_SIZE]; +static module_t boot_modules[MAX_MBI_MODULES]; + + + /* Standard macro to see if a specific flag is changeable. */ static inline int flag_is_changeable_p(unsigned long flag) { @@ -453,36 +469,19 @@ #endif } -void __init __start_xen(multiboot_info_t *mbi) +static int __init boot_param_e820_setup(unsigned char *boot_params, + struct e820entry *e820raw) { - char *cmdline; - module_t *mod = (module_t *)__va(mbi->mods_addr); - void *heap_start; - unsigned long firsthole_start, nr_pages; - unsigned long initial_images_start, initial_images_end; - struct e820entry e820_raw[E820MAX]; - int i, e820_raw_nr = 0, bytes = 0; - - /* Parse the command-line options. */ - if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) ) - cmdline_parse(__va(mbi->cmdline)); - - /* Must do this early -- e.g., spinlocks rely on get_current(). */ - set_current(&idle0_exec_domain); - - /* We initialise the serial devices very early so we can get debugging. */ - serial_init_stage1(); - - init_console(); - - /* Check that we have at least one Multiboot module. */ - if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) ) - { - printk("FATAL ERROR: Require at least one Multiboot module.\n"); - for ( ; ; ) ; - } + int e820_raw_nr = *(int*)&boot_params[E820NR]; + memcpy(e820raw, boot_params + E820MAP, e820_raw_nr * sizeof(*e820raw)); + return e820_raw_nr; +} - xenheap_phys_end = opt_xenheap_megabytes << 20; +static int __init mbi_e820_setup(multiboot_info_t *mbi, + struct e820entry *e820_raw) +{ + int bytes = 0; + int e820_raw_nr = 0; if ( mbi->flags & MBI_MEMMAP ) { @@ -509,14 +508,134 @@ e820_raw[1].type = E820_RAM; e820_raw_nr = 2; } + return e820_raw_nr; +} + +int __init mbi_boot_modules(multiboot_info_t *mbi) +{ + /* Check that we have at least one Multiboot module. */ + if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) ) + { + printk("FATAL ERROR: Require at least one Multiboot module.\n"); + for ( ; ; ) ; + } + + memcpy(&boot_modules, __va(mbi->mods_addr), + sizeof(module_t) * mbi->mods_count); + return mbi->mods_count; +} + +int __init boot_param_modules(unsigned char *params) +{ + u32 rd = *(u32*)&boot_params[INITRD_START]; + int size = *(int*)&boot_params[INITRD_SIZE]; + + boot_modules[0].mod_start = rd; + boot_modules[0].mod_end = rd + size; + boot_modules[0].string = 0; + boot_modules[0].reserved = 0; + + return 1; +} + +void __init __start_xen(void *params) +{ + void *heap_start; + unsigned long firsthole_start, nr_pages; + unsigned long initial_images_start, initial_images_end; + struct e820entry e820_raw[E820MAX]; + int i, e820_raw_nr = 0; + int num_mods = 0; + multiboot_info_t *mbi = NULL; + char *leftover; + unsigned char cmdline[COMMAND_LINE_SIZE + 1]; + unsigned char dom0_cmdline[COMMAND_LINE_SIZE + 1]; + + /* Forces correct empty-string and null-termination behavior */ + memset(cmdline, 0, sizeof(cmdline)); + memset(dom0_cmdline, 0, sizeof(dom0_cmdline)); + + if (MULTIBOOT_BOOTLOADER_MAGIC == *(u32*)__va(params) ) + { + mbi = (struct multiboot_info_t*)__va(mbi); + if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) ) + { + memcpy(cmdline, __va(mbi->cmdline), COMMAND_LINE_SIZE); + } + } + else + { + /* Hope it is a Linux boot parameters area. */ + unsigned char* orig_cmd_line; + memcpy(boot_params, __va(((char*)params)), PARAM_SIZE); + + orig_cmd_line = __va(*(unsigned char**)&boot_params[NEW_CL_POINTER]); + + memcpy(cmdline, orig_cmd_line, COMMAND_LINE_SIZE); + } + + /* Parse the command-line options. */ + leftover = cmdline_parse(cmdline); + + /* Must do this early -- e.g., spinlocks rely on get_current(). */ + set_current(&idle0_exec_domain); + + /* We initialise the serial devices very early so we can get debugging. */ + serial_init_stage1(); + + init_console(); + + xenheap_phys_end = opt_xenheap_megabytes << 20; + + if ( mbi != NULL ) + { + e820_raw_nr = mbi_e820_setup(mbi, e820_raw); + } else { + e820_raw_nr = boot_param_e820_setup(boot_params, e820_raw); + } + + if (e820_raw_nr == 0) + { printk("FATAL ERROR: Bootloader provided no memory information.\n"); for ( ; ; ) ; } max_page = init_e820(e820_raw, e820_raw_nr); + if (mbi != NULL) + { + num_mods = mbi_boot_modules(mbi); + } + else + { + num_mods = boot_param_modules(boot_params); + } + + /* Save dom0 cmd line to a known place. */ + if ( boot_modules[0].string ) + { +#if defined(__i386__) + char *cmdline = (char *)boot_modules[0].string; +#elif defined(__x86_64__) + char *cmdline = (char *)__va(boot_modules[0].string); +#endif + /* Skip past the image name. */ + int i = 0; + while ( cmdline[i] && cmdline[i] == ' ' ) ++i; + while ( cmdline[i] && cmdline[i] != ' ') ++i; + while ( cmdline[i] && cmdline[i] == ' ' ) ++i; + + memcpy(dom0_cmdline, cmdline, COMMAND_LINE_SIZE - i); + } + else if ( leftover ) + { + /* NULL termination is guaranteed on the cmdline buffer, */ + /* and leftover is a pointer into that. */ + strcpy(dom0_cmdline, leftover); + } + /* Find the first high-memory RAM hole. */ for ( i = 0; i < e820.nr_map; i++ ) if ( (e820.map[i].type == E820_RAM) && @@ -527,7 +646,7 @@ /* Relocate the Multiboot modules. */ initial_images_start = xenheap_phys_end; initial_images_end = initial_images_start + - (mod[mbi->mods_count-1].mod_end - mod[0].mod_start); + (boot_modules[num_mods - 1].mod_end - boot_modules[0].mod_start); if ( initial_images_end > firsthole_start ) { printk("Not enough memory to stash the DOM0 kernel image.\n"); @@ -535,14 +654,14 @@ } #if defined(__i386__) memmove((void *)initial_images_start, /* use low mapping */ - (void *)mod[0].mod_start, /* use low mapping */ - mod[mbi->mods_count-1].mod_end - mod[0].mod_start); + (void *)boot_modules[0].mod_start, /* use low mapping */ + boot_modules[num_mods - 1].mod_end - boot_modules[0].mod_start); #elif defined(__x86_64__) memmove(__va(initial_images_start), - __va(mod[0].mod_start), - mod[mbi->mods_count-1].mod_end - mod[0].mod_start); + __va(boot_modules[0].mod_start), + boot_modules[num_mods-1].mod_end - boot_modules[0].mod_start); #endif - + /* Initialise boot-time allocator with all RAM situated after modules. */ heap_start = memguard_init(&_end); heap_start = __va(init_boot_allocator(__pa(heap_start))); @@ -586,28 +705,23 @@ set_bit(DF_PRIVILEGED, &dom0->d_flags); - /* Grab the DOM0 command line. Skip past the image name. */ - cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL); - if ( cmdline != NULL ) - { - while ( *cmdline == ' ' ) cmdline++; - if ( (cmdline = strchr(cmdline, ' ')) != NULL ) - while ( *cmdline == ' ' ) cmdline++; - } - /* * We're going to setup domain0 using the module(s) that we stashed safely * above our heap. The second module, if present, is an initrd ramdisk. */ - if ( construct_dom0(dom0, - initial_images_start, - mod[0].mod_end-mod[0].mod_start, - (mbi->mods_count == 1) ? 0 : - initial_images_start + - (mod[1].mod_start-mod[0].mod_start), - (mbi->mods_count == 1) ? 0 : - mod[mbi->mods_count-1].mod_end - mod[1].mod_start, - cmdline) != 0) + u32 img_size = boot_modules[0].mod_end - boot_modules[0].mod_start; + u32 rd_start = 0; + u32 rd_size = 0; + if ( num_mods > 1 ) + { + rd_start = initial_images_start + + boot_modules[1].mod_start - boot_modules[0].mod_start; + + rd_size = boot_modules[num_mods-1].mod_end - boot_modules[1].mod_start; + } + + if ( construct_dom0(dom0, initial_images_start, img_size, + rd_start, rd_size, dom0_cmdline) != 0) panic("Could not set up DOM0 guest OS\n"); /* Scrub RAM that is still free and so may go to an unprivileged domain. */ diff -Nru a/xen/common/kernel.c b/xen/common/kernel.c --- a/xen/common/kernel.c 2005-03-24 09:20:15 -05:00 +++ b/xen/common/kernel.c 2005-03-24 09:20:15 -05:00 @@ -14,13 +14,14 @@ #include <xen/compile.h> #include <xen/sched.h> -void cmdline_parse(char *cmdline) +/* Returns pointer to unparsed portion of command line. */ +char* cmdline_parse(char *cmdline) { char *opt_end, *opt; struct kernel_param *param; if ( cmdline == NULL ) - return; + return NULL; while ( *cmdline == ' ' ) cmdline++; @@ -31,6 +32,11 @@ cmdline++; if ( *cmdline == '\0' ) break; + + /* Pass all options after -- to dom0 */ + if ( *cmdline == '-' && ( cmdline[1] == '-' || cmdline[1] == '\0' ) ) + return cmdline + 2; + opt_end = strchr(cmdline, ' '); if ( opt_end != NULL ) *opt_end++ = '\0'; @@ -62,6 +68,7 @@ } cmdline = opt_end; } + return NULL; } /* diff -Nru a/xen/include/xen/lib.h b/xen/include/xen/lib.h --- a/xen/include/xen/lib.h 2005-03-24 09:20:15 -05:00 +++ b/xen/include/xen/lib.h 2005-03-24 09:20:15 -05:00 @@ -29,7 +29,8 @@ struct domain; -void cmdline_parse(char *cmdline); +/* Returns pointer to unparsed portion of command line. */ +char* cmdline_parse(char *cmdline); #ifndef NDEBUG extern int debugtrace_send_to_console; diff -Nru a/xen/include/xen/multiboot.h b/xen/include/xen/multiboot.h --- a/xen/include/xen/multiboot.h 2005-03-24 09:20:15 -05:00 +++ b/xen/include/xen/multiboot.h 2005-03-24 09:20:15 -05:00 @@ -28,6 +28,10 @@ #define MBI_MEMMAP (1<<6) #define MBI_LOADERNAME (1<<9) +/* Make up some reasonable maximum that we support. */ +#define MAX_MBI_MODULES 4 + + /* The symbol table for a.out. */ typedef struct { u32 tabsize; Attachment:
signature.asc
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |