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

[Xen-devel] [PATCH for-xen-4.5 v4 06/18] 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>
---
v4 - suggestions/fixes:
   - rename reloc() function
     (suggested by Andrew Cooper),
   - rename enable_bsp_exception_support() function
     (suggested by Andrew Cooper),
   - move enable_bsp_exception_support() function
     declaration to header file
     (suggested by Andrew Cooper and Jan Beulich),
   - change sizeof(<expression>) to sizeof(<type>) where possible
     (suggested by Jan Beulich),
   - set only mbi flag only if relevant data is valid
     (suggested by Jan Beulich),
   - improve inline assembly
     (suggested by Andrew Cooper),
   - improve comments
     (suggested by Andrew Cooper),
   - fix copyright
     (suggested by Konrad Rzeszutek Wilk),
   - fix coding style
     (suggested by Andrew Cooper, Jan Beulich and Konrad Rzeszutek Wilk).

v3 - suggestions/fixes:
   - rename some variables
     (suggested by Andrew Cooper),
   - remove unneeded initialization
     (suggested by Andrew Cooper),
   - improve comments
     (suggested by Andrew Cooper),
   - further patch split rearrangement
     (suggested by Andrew Cooper and Jan Beulich).

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/Makefile        |    3 +-
 xen/arch/x86/boot/cmdline.S       |    9 ++---
 xen/arch/x86/boot/head.S          |    2 +-
 xen/arch/x86/boot/reloc.c         |   66 ++++++++++++++++++++----------
 xen/arch/x86/boot/x86_64.S        |   10 +++--
 xen/arch/x86/boot_info.c          |   70 ++++++++++++++++++++++++++++++++
 xen/arch/x86/efi/efi-boot.h       |    2 +-
 xen/arch/x86/setup.c              |   42 +++++++++++--------
 xen/arch/x86/x86_64/asm-offsets.c |    6 +--
 xen/include/asm-x86/mbd.h         |   80 +++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/setup.h       |    2 +
 12 files changed, 241 insertions(+), 52 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 86ca5f8..8425e65 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -43,6 +43,7 @@ obj-y += pci.o
 obj-y += percpu.o
 obj-y += physdev.o
 obj-y += psr.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/Makefile b/xen/arch/x86/boot/Makefile
index 3cab36a..e6ff2b7 100644
--- a/xen/arch/x86/boot/Makefile
+++ b/xen/arch/x86/boot/Makefile
@@ -1,6 +1,7 @@
 obj-bin-y += head.o
 
-RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h 
$(BASEDIR)/include/xen/multiboot.h
+RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h 
$(BASEDIR)/include/xen/compiler.h \
+            $(BASEDIR)/include/xen/multiboot.h $(BASEDIR)/include/asm-x86/mbd.h
 
 export RELOC_DEPS
 
diff --git a/xen/arch/x86/boot/cmdline.S b/xen/arch/x86/boot/cmdline.S
index 00687eb..b622c6b 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_pa),%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 0bdbc65..64a0ff7 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -120,7 +120,7 @@ __start:
         mov     $sym_phys(cpu0_stack)+1024,%esp
         push    %ebx
         call    reloc
-        mov     %eax,sym_phys(multiboot_ptr)
+        mov     %eax,sym_phys(mbd_pa)
 
         /* 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 e1c83f4..9792fcd 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -31,8 +31,12 @@ asm (
     );
 
 typedef unsigned int u32;
+
+#include "../../../include/xen/compiler.h"
 #include "../../../include/xen/multiboot.h"
 
+#include "../../../include/asm/mbd.h"
+
 static u32 alloc_struct(u32 bytes)
 {
     u32 s;
@@ -49,6 +53,11 @@ static u32 alloc_struct(u32 bytes)
     return s;
 }
 
+static void zero_struct(u32 s, u32 bytes)
+{
+    asm volatile("rep stosb" : "+D" (s), "+c" (bytes) : "a" (0));
+}
+
 static u32 copy_struct(u32 src, u32 bytes)
 {
     u32 dst, dst_asm;
@@ -74,41 +83,56 @@ static u32 copy_string(u32 src)
     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 = (multiboot_info_t *)copy_struct((u32)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 = copy_string(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 = (module_t *)copy_struct(
-            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 = copy_string(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 = copy_struct(mbi->mmap_addr, mbi->mmap_length);
+    return mbd;
+}
 
-    if ( mbi->flags & MBI_LOADERNAME )
-        mbi->boot_loader_name = copy_string(mbi->boot_loader_name);
+static mbd_t __used *reloc(void *mbi)
+{
+    mbd_t *mbd;
 
-    /* Mask features we don't understand or don't relocate. */
-    mbi->flags &= (MBI_MEMLIMITS |
-                   MBI_BOOTDEV |
-                   MBI_CMDLINE |
-                   MBI_MODULES |
-                   MBI_MEMMAP |
-                   MBI_LOADERNAME);
+    mbd = (mbd_t *)alloc_struct(sizeof(*mbd));
+    zero_struct((u32)mbd, sizeof(*mbd));
 
-    return mbi;
+    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..fc7ce74 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
+        /* Initialize the Multiboot info struct. */
+        mov     mbd_pa(%rip),%edi
+        call    __init_mbi
+
+        /* Pass off the Multiboot info struct 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_pa:
         .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..64bc4d9
--- /dev/null
+++ b/xen/arch/x86/boot_info.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle Corp.
+ *      Author: 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/cache.h>
+#include <xen/init.h>
+#include <xen/multiboot.h>
+
+#include <asm/mbd.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+static multiboot_info_t __read_mostly mbi;
+
+unsigned long __init __init_mbi(u32 mbd_pa)
+{
+    mbd_t *mbd = __va(mbd_pa);
+
+    enable_bsp_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;
+    }
+
+    if ( mbd->mem_lower || mbd->mem_upper )
+    {
+        mbi.flags |= MBI_MEMLIMITS;
+        mbi.mem_lower = mbd->mem_lower;
+        mbi.mem_upper = mbd->mem_upper;
+    }
+
+    if ( mbd->mmap_size )
+    {
+        mbi.flags |= MBI_MEMMAP;
+        mbi.mmap_length = mbd->mmap_size;
+        mbi.mmap_addr = mbd->mmap;
+    }
+
+    if ( mbd->mods_nr )
+    {
+        mbi.flags |= MBI_MODULES;
+        mbi.mods_count = mbd->mods_nr;
+        mbi.mods_addr = mbd->mods;
+    }
+
+    return (unsigned long)&mbi;
+}
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 4348cfe..5c85854 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -245,7 +245,7 @@ static void __init noreturn efi_arch_post_exit_boot(void)
                      [cs] "ir" (__HYPERVISOR_CS),
                      [ds] "r" (__HYPERVISOR_DS),
                      [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)),
-                     "D" (&mbi)
+                     "D" (__va(&mbi))
                    : "memory" );
     for( ; ; ); /* not reached */
 }
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index bfbb310..eacb9b2 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -529,12 +529,29 @@ static char * __init cmdline_cook(char *p, const char 
*loader_name)
     return p;
 }
 
+void __init enable_bsp_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();
+}
+
 void __init noreturn __start_xen(unsigned long mbi_p)
 {
     char *memmap_type = NULL;
     char *cmdline, *kextra, *loader;
     unsigned int initrdidx, domcr_flags = DOMCRF_s3_integrity;
-    multiboot_info_t *mbi = __va(mbi_p);
+    multiboot_info_t *mbi = (multiboot_info_t *)mbi_p;
     module_t *mod = (module_t *)__va(mbi->mods_addr);
     unsigned long nr_pages, raw_max_page, modules_headroom, *module_map;
     int i, j, e820_warn = 0, bytes = 0;
@@ -546,21 +563,14 @@ 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 )
+    {
+        enable_bsp_exception_support();
+    }
+    else
+    {
+        /* Exception support was enabled before __start_xen() call. */
+    }
 
     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 2de9cad..7364dd6 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -9,10 +9,11 @@
 #include <xen/perfc.h>
 #include <xen/sched.h>
 #include <xen/bitops.h>
+#include <xen/multiboot.h>
 #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 " */<==\"" \
@@ -166,6 +167,5 @@ void __dummy__(void)
     OFFSET(MBI_mem_lower, multiboot_info_t, mem_lower);
     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..11c7bcd
--- /dev/null
+++ b/xen/include/asm-x86/mbd.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle Corp.
+ *      Author: 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__
+
+/*
+ * Do not include any headers here!
+ *
+ * This file is used by xen/arch/x86/boot/reloc.c
+ * and any include statement here will break its build.
+ * It means that every basic type used below must be defined
+ * before any usage of this header.
+ */
+
+/* Module type. */
+typedef struct {
+    u32 start;
+    u32 end;
+
+    /* A module command line address. */
+    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 {
+    /* Boot loader name physical address. */
+    u32 boot_loader_name;
+
+    /* Xen command line physical address. */
+    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;
+
+    /* Physical address of memory map provided by bootloader. */
+    u32 mmap;
+
+    /* Number of modules. */
+    u32 mods_nr;
+
+    /* Physical address of an array of module descriptions (boot_module_t *). 
*/
+    u32 mods;
+} mbd_t;
+#endif /* __MBD_H__ */
diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
index 8f8c6f3..d051ee6 100644
--- a/xen/include/asm-x86/setup.h
+++ b/xen/include/asm-x86/setup.h
@@ -5,6 +5,8 @@
 
 extern unsigned long xenheap_initial_phys_start;
 
+extern void enable_bsp_exception_support(void);
+
 void early_cpu_init(void);
 void early_time_init(void);
 
-- 
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®.