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;
signature.asc
Description: This is a digitally signed message part
|