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

Re: [Xen-devel] [PATCH RFC 4/7] xen/x86: Migrate to XBI structure



On 09/08/14 00:04, Daniel Kiper wrote:
> We have all constants and structures in place. So, finally break multiboot 
> (v1)
> protocol dependency. It means that most of Xen code (excluding preloader)
> could be bootloader agnostic and does not need almost any knowledge about
> boot protocol. Additionally, we are able to pass all boot data to 
> __start_xen()
> in one bucket without any side channels. I do not mention that we are also
> able to easily identify boot data in Xen code.
>
> Here is boot data flow for legacy BIOS platform:
>
>   BIOS -> GRUB -> multiboot[12]* -> __reloc() -> MBD ->-\
>                                                         /
>                      -----------------<-----------------
>                      \
>                       \
>                        ---> __init_xbi() -> XBI_MB -> __start_xen() -> XBI
>                       /
>              BIOS ->-/
>
>   * multiboot2 is not implemented yet. Look for it in next patch.
>
> Here is boot data flow for EFI platform:
>
>   EFI -> efi_start() -> XBI_EFI -> __start_xen() -> XBI
>
> WARNING: ARM build could be broken by this patch. We need to agree XBI
> integration into ARM. Personally I think that it is worth storing all
> data from any bootloader and preloader in XBI on any architecture. This
> give a chance to share more code between architectures. However, every
> architecture should define its own XBI (in relevant include/asm directory).
> Despite that it looks that some parts of it could be common, e.g.  modules
> data, command line arguments, boot loader name, EFI data, etc., even if types
> would not be the same. So, as it was stated above a lot of code could be
> shared among architectures.
>
> Signed-off-by: Daniel Kiper <daniel.kiper@xxxxxxxxxx>

This patch is massive, and really needs splitting up somewhat.  There
are several logically distinct bits to it.

> ---
>  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         |  153 ++++++++++++-----
>  xen/arch/x86/boot/x86_64.S        |   10 +-
>  xen/arch/x86/dmi_scan.c           |    7 +-
>  xen/arch/x86/domain_build.c       |   24 +--
>  xen/arch/x86/efi/boot.c           |  212 +++++++++++------------
>  xen/arch/x86/efi/efi.h            |    3 -
>  xen/arch/x86/efi/runtime.c        |   52 ++++--
>  xen/arch/x86/init_xbi.c           |  254 +++++++++++++++++++++++++++
>  xen/arch/x86/microcode.c          |   39 ++---
>  xen/arch/x86/mpparse.c            |    9 +-
>  xen/arch/x86/platform_hypercall.c |   19 +--
>  xen/arch/x86/setup.c              |  340 
> +++++++++++--------------------------
>  xen/arch/x86/x86_64/asm-offsets.c |    5 +-
>  xen/drivers/acpi/osl.c            |    9 +-
>  xen/drivers/video/vesa.c          |    5 +-
>  xen/drivers/video/vga.c           |   16 +-
>  xen/include/asm-x86/config.h      |    2 -
>  xen/include/asm-x86/e820.h        |    8 -
>  xen/include/asm-x86/edd.h         |    6 -
>  xen/include/asm-x86/setup.h       |   10 +-
>  xen/include/xen/efi.h             |   10 --
>  xen/include/xen/vga.h             |    4 -
>  xen/include/xsm/xsm.h             |   14 +-
>  xen/xsm/xsm_core.c                |    6 +-
>  xen/xsm/xsm_policy.c              |   14 +-
>  28 files changed, 723 insertions(+), 549 deletions(-)
>  create mode 100644 xen/arch/x86/init_xbi.c
>
> diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
> index c1e244d..bb2264a 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 += init_xbi.o

init_xbi is not a fantastic filename.  xbi alone would be better
(subject to my concerned about the name xbi).

>  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

FLAGS & MBI_CMDLINE is the prerequisite for the 'cmdline' field being
valid.  You cannot drop that check (although making use of some manifest
constants would help)

>          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..29f4887 100644
> --- a/xen/arch/x86/boot/reloc.c
> +++ b/xen/arch/x86/boot/reloc.c
> @@ -1,40 +1,56 @@
> -/******************************************************************************
> +/*
>   * 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/multiboot.h"
> +#include "../../../include/asm/mbd.h"
> +
> +/*
> + * __HERE__ IS TRUE 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 +58,105 @@ 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(
> +    "    cld                          \n"

__start has already performed cld for us.  There is nothing which will
have set it between then and here.

> +    "    xor  %%eax,%%eax             \n"
> +    "    rep  stosb                   \n"
> +       : "+D" (s), "+c" (bytes) : : "eax");

Why not "a" (0) and drop the xor and eax clobber?

> +}
> +
> +static u32 copy_struct(u32 src, u32 bytes)
> +{
> +    u32 dst;
> +
> +    dst = alloc_struct(bytes);
> +
> +    asm volatile(
> +    "    cld                          \n"
> +    "    mov  %2,%%edi                \n"
>      "    rep  movsb                   \n"
> -       : "=&r" (new), "+c" (bytes), "+S" (old)
> -     : : "edx", "edi");
> -    return new;
> +       : "+S" (src), "+c" (bytes) : "r" (dst) : "edi");

Again, drop the mov %2,%%edi and use proper parameters without clobbers

> +
> +    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;
> +    module_t *mbi_mods;
> +    boot_module_t *mbd_mods;
> +
> +    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;
> +/*
> + * __THIS__ IS NOT ENTRY POINT!!!
> + * PLEASE LOOK AT THE BEGINNING OF THIS FILE!!!

I don't think this needs stating...

> + *
> + * It could be a static but then compiler complains:
> + * error: â__relocâ defined but not used.
> + */
> +mbd_t *__reloc(void *mbi, u32 mb_magic)

static mbd_t *__reloc(void *mbi, u32 mb_magic) __attribute__((used)) is
the correct way of informing gcc that it is referenced from inline assembly.

> +{
> +    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..ec39d38 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 Xen Boot Info. */
> +        mov     mbd_ptr(%rip),%edi
> +        call    __init_xbi

This is a large quantity of code shuffling bits of data, which does not
strictly need to be done at this point.

Please defer it until after full trap support has been set up in
__start_xen().

~Andrew

_______________________________________________
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®.