[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 1/5] xen/x86: Introduce MultiBoot Data (MBD) type



Introduce MultiBoot Data (MBD) type. It is used to define variable
which carry over data from multiboot protocol (any version) through
Xen preloader stage. Later all or parts of this data is used
to initialize boot_info structure. boot_info is introduced
in later patches.

MBD helps to break multiboot (v1) protocol dependency. Using it
we are able to save space on trampoline (we do not allocate space
for unused data what happens in current preloader implementation).
Additionally, we are able to easily add new members to MBD if we
want support for new features or protocols.

There is not plan to share MBD among architectures. It will be
nice if boot_info will be shared among architectures. Please
check later patches for more details.

Code found in xen/arch/x86/boot_info.c moves MBD data to mbi struct
which is referenced from main Xen code. This is temporary solution
which helps to split patches into logical parts. Later it will be
replaced by final version of boot_info support.

Signed-off-by: Daniel Kiper <daniel.kiper@xxxxxxxxxx>
---
v2 - suggestions/fixes:
   - improve inline assembly
     (suggested by Andrew Cooper and Jan Beulich),
   - use __used attribute
     (suggested by Andrew Cooper),
   - patch split rearrangement
     (suggested by Andrew Cooper and Jan Beulich).
---
 xen/arch/x86/Makefile             |    1 +
 xen/arch/x86/boot/cmdline.S       |    9 +--
 xen/arch/x86/boot/head.S          |   31 ++++----
 xen/arch/x86/boot/reloc.c         |  147 +++++++++++++++++++++++++------------
 xen/arch/x86/boot/x86_64.S        |   10 ++-
 xen/arch/x86/boot_info.c          |   58 +++++++++++++++
 xen/arch/x86/setup.c              |   41 +++++++----
 xen/arch/x86/x86_64/asm-offsets.c |    5 +-
 xen/include/asm-x86/mbd.h         |   70 ++++++++++++++++++
 9 files changed, 284 insertions(+), 88 deletions(-)
 create mode 100644 xen/arch/x86/boot_info.c
 create mode 100644 xen/include/asm-x86/mbd.h

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index c1e244d..c465bb3 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -42,6 +42,7 @@ obj-y += numa.o
 obj-y += pci.o
 obj-y += percpu.o
 obj-y += physdev.o
+obj-y += boot_info.o
 obj-y += setup.o
 obj-y += shutdown.o
 obj-y += smp.o
diff --git a/xen/arch/x86/boot/cmdline.S b/xen/arch/x86/boot/cmdline.S
index 00687eb..7316011 100644
--- a/xen/arch/x86/boot/cmdline.S
+++ b/xen/arch/x86/boot/cmdline.S
@@ -152,17 +152,14 @@ cmdline_parse_early:
         pusha
 
         /* Bail if there is no command line to parse. */
-        mov     sym_phys(multiboot_ptr),%ebx
-        mov     MB_flags(%ebx),%eax
-        test    $4,%al
-        jz      .Lcmdline_exit
-        mov     MB_cmdline(%ebx),%eax
+        mov     sym_phys(mbd_ptr),%ebx
+        mov     MBD_cmdline(%ebx),%eax
         test    %eax,%eax
         jz      .Lcmdline_exit
 
         /* Check for 'no-real-mode' command-line option. */
         pushl   $sym_phys(.Lno_rm_opt)
-        pushl   MB_cmdline(%ebx)
+        pushl   MBD_cmdline(%ebx)
         call    .Lfind_option
         test    %eax,%eax
         setnz   %al
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 10ecf51..79bce3c 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -86,14 +86,14 @@ __start:
         jne     not_multiboot
 
         /* Set up trampoline segment 64k below EBDA */
-        movzwl  0x40e,%eax          /* EBDA segment */
-        cmp     $0xa000,%eax        /* sanity check (high) */
+        movzwl  0x40e,%ecx          /* EBDA segment */
+        cmp     $0xa000,%ecx        /* sanity check (high) */
         jae     0f
-        cmp     $0x4000,%eax        /* sanity check (low) */
+        cmp     $0x4000,%ecx        /* sanity check (low) */
         jae     1f
 0:
-        movzwl  0x413,%eax          /* use base memory size on failure */
-        shl     $10-4,%eax
+        movzwl  0x413,%ecx          /* use base memory size on failure */
+        shl     $10-4,%ecx
 1:
         /*
          * Compare the value in the BDA with the information from the
@@ -105,22 +105,23 @@ __start:
         cmp     $0x100,%edx         /* is the multiboot value too small? */
         jb      2f                  /* if so, do not use it */
         shl     $10-4,%edx
-        cmp     %eax,%edx           /* compare with BDA value */
-        cmovb   %edx,%eax           /* and use the smaller */
+        cmp     %ecx,%edx           /* compare with BDA value */
+        cmovb   %edx,%ecx           /* and use the smaller */
 
 2:      /* Reserve 64kb for the trampoline */
-        sub     $0x1000,%eax
+        sub     $0x1000,%ecx
 
         /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */
-        xor     %al, %al
-        shl     $4, %eax
-        mov     %eax,sym_phys(trampoline_phys)
+        xor     %cl, %cl
+        shl     $4, %ecx
+        mov     %ecx,sym_phys(trampoline_phys)
 
-        /* Save the Multiboot info struct (after relocation) for later use. */
+        /* Save the Multiboot data (after relocation) for later use. */
         mov     $sym_phys(cpu0_stack)+1024,%esp
-        push    %ebx
-        call    reloc
-        mov     %eax,sym_phys(multiboot_ptr)
+        push    %eax                /* Multiboot magic */
+        push    %ebx                /* Multiboot information address */
+        call    reloc               /* %ecx contains trampoline address */
+        mov     %eax,sym_phys(mbd_ptr)
 
         /* Initialize BSS (no nasty surprises!) */
         mov     $sym_phys(__bss_start),%edi
diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index fa0fb6b..35a991e 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -1,40 +1,58 @@
-/******************************************************************************
+/*
  * 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.
- * 
+ * Copyright (c) 2013, 2014 Oracle Co., Daniel Kiper
+ *
  * Authors:
  *    Keir Fraser <keir@xxxxxxx>
+ *    Daniel Kiper
  */
 
-/* entered with %eax = BOOT_TRAMPOLINE */
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+typedef unsigned long long u64;
+
+#include "../../../include/xen/compiler.h"
+#include "../../../include/xen/multiboot.h"
+
+#include "../../../include/asm/mbd.h"
+
+/*
+ * __HERE__ IS ENTRY POINT!!!
+ *
+ * It is entered from xen/arch/x86/boot/head.S with:
+ *   - %eax = MULTIBOOT_MAGIC,
+ *   - %ebx = MULTIBOOT_INFORMATION_ADDRESS,
+ *   - %ecx = BOOT_TRAMPOLINE.
+ */
 asm (
     "    .text                         \n"
     "    .globl _start                 \n"
     "_start:                           \n"
     "    call 1f                       \n"
     "1:  pop  %ebx                     \n"
-    "    mov  %eax,alloc-1b(%ebx)      \n"
-    "    jmp  reloc                    \n"
+    "    mov  %ecx,alloc-1b(%ebx)      \n"
+    "    jmp  __reloc                  \n"
     );
 
-/* This is our data.  Because the code must be relocatable, no BSS is
- * allowed.  All data is accessed PC-relative with inline assembly.
+/*
+ * This is our data. Because the code must be relocatable, no BSS is
+ * allowed. All data is accessed PC-relative with inline assembly.
  */
 asm (
     "alloc:                            \n"
     "    .long 0                       \n"
     );
 
-typedef unsigned int u32;
-#include "../../../include/xen/multiboot.h"
-
-static void *reloc_mbi_struct(void *old, unsigned int bytes)
+static u32 alloc_struct(u32 bytes)
 {
-    void *new;
+    u32 s;
+
     asm(
     "    call 1f                      \n"
     "1:  pop  %%edx                   \n"
@@ -42,58 +60,95 @@ static void *reloc_mbi_struct(void *old, unsigned int bytes)
     "    sub  %1,%0                   \n"
     "    and  $~15,%0                 \n"
     "    mov  %0,alloc-1b(%%edx)      \n"
-    "    mov  %0,%%edi                \n"
+       : "=&r" (s) : "r" (bytes) : "edx");
+
+    return s;
+}
+
+static void zero_struct(u32 s, u32 bytes)
+{
+    asm volatile(
+    "    rep  stosb                   \n"
+       : "+D" (s), "+c" (bytes) : "a" (0));
+}
+
+static u32 copy_struct(u32 src, u32 bytes)
+{
+    u32 dst, dst_asm;
+
+    dst = alloc_struct(bytes);
+    dst_asm = dst;
+
+    asm volatile(
     "    rep  movsb                   \n"
-       : "=&r" (new), "+c" (bytes), "+S" (old)
-       : : "edx", "edi");
-    return new;
+       : "+S" (src), "+D" (dst_asm), "+c" (bytes));
+
+    return dst;
 }
 
-static char *reloc_mbi_string(char *old)
+static u32 copy_string(u32 src)
 {
     char *p;
-    for ( p = old; *p != '\0'; p++ )
+
+    if ( src == 0 )
+        return 0;
+
+    for ( p = (char *)src; *p != '\0'; p++ )
         continue;
-    return reloc_mbi_struct(old, p - old + 1);
+
+    return copy_struct(src, p - (char *)src + 1);
 }
 
-multiboot_info_t *reloc(multiboot_info_t *mbi_old)
+static mbd_t *mb_mbd(mbd_t *mbd, multiboot_info_t *mbi)
 {
-    multiboot_info_t *mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi));
-    int i;
+    boot_module_t *mbd_mods;
+    module_t *mbi_mods;
+    u32 i;
+
+    if ( mbi->flags & MBI_LOADERNAME )
+        mbd->boot_loader_name = copy_string(mbi->boot_loader_name);
 
     if ( mbi->flags & MBI_CMDLINE )
-        mbi->cmdline = (u32)reloc_mbi_string((char *)mbi->cmdline);
+        mbd->cmdline = copy_string(mbi->cmdline);
+
+    if ( mbi->flags & MBI_MEMLIMITS )
+    {
+        mbd->mem_lower = mbi->mem_lower;
+        mbd->mem_upper = mbi->mem_upper;
+    }
+
+    if ( mbi->flags & MBI_MEMMAP )
+    {
+        mbd->mmap_size = mbi->mmap_length;
+        mbd->mmap = copy_struct(mbi->mmap_addr, mbi->mmap_length);
+    }
 
     if ( mbi->flags & MBI_MODULES )
     {
-        module_t *mods = reloc_mbi_struct(
-            (module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t));
+        mbd->mods_nr = mbi->mods_count;
+        mbd->mods = alloc_struct(mbi->mods_count * sizeof(boot_module_t));
 
-        mbi->mods_addr = (u32)mods;
+        mbi_mods = (module_t *)mbi->mods_addr;
+        mbd_mods = (boot_module_t *)mbd->mods;
 
         for ( i = 0; i < mbi->mods_count; i++ )
         {
-            if ( mods[i].string )
-                mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string);
+            mbd_mods[i].start = mbi_mods[i].mod_start;
+            mbd_mods[i].end = mbi_mods[i].mod_end;
+            mbd_mods[i].cmdline = copy_string(mbi_mods[i].string);
+            mbd_mods[i].relocated = 0;
         }
     }
 
-    if ( mbi->flags & MBI_MEMMAP )
-        mbi->mmap_addr = (u32)reloc_mbi_struct(
-            (memory_map_t *)mbi->mmap_addr, mbi->mmap_length);
+    return mbd;
+}
 
-    if ( mbi->flags & MBI_LOADERNAME )
-        mbi->boot_loader_name = (u32)reloc_mbi_string(
-            (char *)mbi->boot_loader_name);
-
-    /* Mask features we don't understand or don't relocate. */
-    mbi->flags &= (MBI_MEMLIMITS |
-                   MBI_BOOTDEV |
-                   MBI_CMDLINE |
-                   MBI_MODULES |
-                   MBI_MEMMAP |
-                   MBI_LOADERNAME);
-
-    return mbi;
+static mbd_t __used *__reloc(void *mbi, u32 mb_magic)
+{
+    mbd_t *mbd;
+
+    mbd = (mbd_t *)alloc_struct(sizeof(mbd_t));
+    zero_struct((u32)mbd, sizeof(mbd_t));
+
+    return mb_mbd(mbd, mbi);
 }
diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S
index bfbafd2..34243b1 100644
--- a/xen/arch/x86/boot/x86_64.S
+++ b/xen/arch/x86/boot/x86_64.S
@@ -29,8 +29,12 @@
         test    %ebx,%ebx
         jnz     start_secondary
 
-        /* Pass off the Multiboot info structure to C land. */
-        mov     multiboot_ptr(%rip),%edi
+        /* Init boot_info. */
+        mov     mbd_ptr(%rip),%edi
+        call    __init_boot_info
+
+        /* Pass off the boot_info to C land. */
+        movq    %rax,%rdi
         call    __start_xen
         ud2     /* Force a panic (invalid opcode). */
 
@@ -38,7 +42,7 @@
 
         .data
         .align 8
-multiboot_ptr:
+mbd_ptr:
         .long   0
 
         .word   0
diff --git a/xen/arch/x86/boot_info.c b/xen/arch/x86/boot_info.c
new file mode 100644
index 0000000..70830c2
--- /dev/null
+++ b/xen/arch/x86/boot_info.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle Co., Daniel Kiper
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/types.h>
+#include <xen/init.h>
+#include <xen/multiboot.h>
+
+#include <asm/mbd.h>
+#include <asm/page.h>
+
+static multiboot_info_t mbi = {};
+
+extern void enable_exception_support(void);
+
+unsigned long __init __init_boot_info(u32 mbd_ptr)
+{
+    mbd_t *mbd = __va(mbd_ptr);
+
+    enable_exception_support();
+
+    if ( mbd->boot_loader_name ) {
+        mbi.flags = MBI_LOADERNAME;
+        mbi.boot_loader_name = mbd->boot_loader_name;
+    }
+
+    if ( mbd->cmdline ) {
+        mbi.flags |= MBI_CMDLINE;
+        mbi.cmdline = mbd->cmdline;
+    }
+
+    mbi.flags |= MBI_MEMLIMITS;
+    mbi.mem_lower = mbd->mem_lower;
+    mbi.mem_upper = mbd->mem_upper;
+
+    mbi.flags |= MBI_MEMMAP;
+    mbi.mmap_length = mbd->mmap_size;
+    mbi.mmap_addr = mbd->mmap;
+
+    mbi.flags |= MBI_MODULES;
+    mbi.mods_count = mbd->mods_nr;
+    mbi.mods_addr = mbd->mods;
+
+    return __pa(&mbi);
+}
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 6a814cd..9391efa 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -539,6 +539,25 @@ static char * __init cmdline_cook(char *p, char 
*loader_name)
     return p;
 }
 
+void __init enable_exception_support(void)
+{
+    /* Critical region without IDT or TSS.  Any fault is deadly! */
+
+    set_processor_id(0);
+    set_current((struct vcpu *)0xfffff000); /* debug sanity. */
+    idle_vcpu[0] = current;
+
+    percpu_init_areas();
+
+    init_idt_traps();
+    load_system_tables();
+
+    smp_prepare_boot_cpu();
+    sort_exception_tables();
+
+    /* Full exception support from here on in. */
+}
+
 void __init noreturn __start_xen(unsigned long mbi_p)
 {
     char *memmap_type = NULL;
@@ -556,21 +575,13 @@ void __init noreturn __start_xen(unsigned long mbi_p)
         .stop_bits = 1
     };
 
-    /* Critical region without IDT or TSS.  Any fault is deadly! */
-
-    set_processor_id(0);
-    set_current((struct vcpu *)0xfffff000); /* debug sanity. */
-    idle_vcpu[0] = current;
-
-    percpu_init_areas();
-
-    init_idt_traps();
-    load_system_tables();
-
-    smp_prepare_boot_cpu();
-    sort_exception_tables();
-
-    /* Full exception support from here on in. */
+    if ( !efi_enabled ) {
+        /* Exception support was enabled before __start_xen() call. */
+    }
+    else
+    {
+        enable_exception_support();
+    }
 
     loader = (mbi->flags & MBI_LOADERNAME)
         ? (char *)__va(mbi->boot_loader_name) : "unknown";
diff --git a/xen/arch/x86/x86_64/asm-offsets.c 
b/xen/arch/x86/x86_64/asm-offsets.c
index 3994f4d..2123eb3 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -12,7 +12,7 @@
 #include <compat/xen.h>
 #include <asm/fixmap.h>
 #include <asm/hardirq.h>
-#include <xen/multiboot.h>
+#include <asm/mbd.h>
 
 #define DEFINE(_sym, _val)                                                 \
     asm volatile ("\n.ascii\"==>#define " #_sym " %0 /* " #_val " */<==\"" \
@@ -163,6 +163,5 @@ void __dummy__(void)
     OFFSET(CPUINFO_features, struct cpuinfo_x86, x86_capability);
     BLANK();
 
-    OFFSET(MB_flags, multiboot_info_t, flags);
-    OFFSET(MB_cmdline, multiboot_info_t, cmdline);
+    OFFSET(MBD_cmdline, mbd_t, cmdline);
 }
diff --git a/xen/include/asm-x86/mbd.h b/xen/include/asm-x86/mbd.h
new file mode 100644
index 0000000..96e3044
--- /dev/null
+++ b/xen/include/asm-x86/mbd.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle Co., Daniel Kiper
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MBD_H__
+#define __MBD_H__
+
+/* Module type. */
+typedef struct {
+    u32 start;
+    u32 end;
+
+    /* Pointer to a module command line. */
+    u32 cmdline;
+
+    /* If relocated != 0 then a given module was relocated. */
+    u32 relocated;
+} boot_module_t;
+
+/*
+ * MultiBoot Data (MBD) type. It is used to define variable which
+ * carry over data from multiboot protocol (any version) through
+ * Xen preloader stage. Later all or parts of this data is used
+ * to initialize boot_info structure.
+ */
+typedef struct {
+    /* Pointer to boot loader name. */
+    u32 boot_loader_name;
+
+    /* Pointer to Xen command line. */
+    u32 cmdline;
+
+    /*
+     * Amount of lower memory (in KiB) accordingly to The Multiboot
+     * Specification version 0.6.96.
+     */
+    u32 mem_lower;
+
+    /*
+     * Amount of upper memory (in KiB) accordingly to The Multiboot
+     * Specification version 0.6.96.
+     */
+    u32 mem_upper;
+
+    /* Size (in bytes) of memory map provided by bootloader. */
+    u32 mmap_size;
+
+    /* Pointer to memory map provided by bootloader. */
+    u32 mmap;
+
+    /* Number of modules. */
+    u32 mods_nr;
+
+    /* Pointer to modules description (boot_module_t *). */
+    u32 mods;
+} mbd_t;
+#endif /* __MBD_H__ */
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.