Xeon Phi boot: getting rid of the single boot image and dependencies
authorReto Achermann <reto.achermann@inf.ethz.ch>
Thu, 25 Jun 2015 14:52:54 +0000 (16:52 +0200)
committerReto Achermann <reto.achermann@inf.ethz.ch>
Thu, 25 Jun 2015 15:11:38 +0000 (17:11 +0200)
Adapting the boot protocol of the Xeon Phi cards to dynamically
load the individual modules at run time rather than compile time.

The following sources can be used to load the modules
- in ramfs of host machine
- from a TFTP server (using the --tftp flag)
- from NFS (using the --nfs flag)

The modules to be loaded are specified in a supplied menu.lst file.
The parameter  --modlist can be used to specify that file.

The boot driver will handle the generation of the needed data structures
and headers when the card boots.

Signed-off-by: Reto Achermann <reto.achermann@inf.ethz.ch>

16 files changed:
hake/symbolic_targets.mk
include/xeon_phi/xeon_phi.h
kernel/arch/k1om/startup_arch.c
tools/weever/Hakefile
tools/weever/creator/Hakefile [deleted file]
tools/weever/creator/weever_creator.c [deleted file]
tools/weever/install.sh [deleted file]
tools/weever/loader.c
tools/weever/mbi.h [deleted file]
tools/weever/multiboot/Hakefile [deleted file]
tools/weever/multiboot/build_data_files.sh [deleted file]
tools/weever/multiboot/weever_multiboot.c [deleted file]
usr/drivers/xeon_phi/Hakefile
usr/drivers/xeon_phi/boot.c
usr/drivers/xeon_phi/main_host.c
usr/drivers/xeon_phi/xeon_phi_internal.h

index c1ffed4..3f1c589 100644 (file)
@@ -26,8 +26,6 @@ ARM_GCC?=arm-linux-gnueabi-gcc
 ARM_OBJCOPY?=arm-linux-gnueabi-objcopy
 K1OM_OBJCOPY?=k1om-mpss-linux-objcopy
 
-# upload Xeon Phi images to nfs share (leave blank to cancel)
-BARRELFISH_NFS_DIR ?="emmentaler1.ethz.ch:/mnt/local/nfs/barrelfish/xeon_phi"
 
 # All binaries of the RCCE LU benchmark
 BIN_RCCE_LU= \
@@ -172,7 +170,7 @@ BENCH_k1om=\
        sbin/benchmarks/xomp_spawn \
        sbin/benchmarks/xomp_work \
        sbin/benchmarks/xphi_ump_bench \
-       sbin/benchmarks/xphi_xump_bench
+       sbin/benchmarks/xphi_xump_bench 
 
 
 # Default list of modules to build/install for all enabled architectures
@@ -248,8 +246,7 @@ MODULES_k1om= \
        sbin/weever \
        sbin/cpu \
        sbin/xeon_phi \
-       sbin/corectrl \
-       xeon_phi_multiboot \
+       sbin/corectrl 
 
 # the following are broken in the newidc system
 MODULES_x86_64_broken= \
@@ -361,23 +358,14 @@ install: $(MODULES)
        for m in ${MODULES}; do \
          if [ ! -f ${INSTALL_PREFIX}/$$m ] || \
              [ $$(stat -c%Y $$m) -ne $$(stat -c%Y ${INSTALL_PREFIX}/$$m) ]; then \
-              if [ "$$m" != "k1om/xeon_phi_multiboot" ]; then \
                 do_update=1; \
                 echo "  > Installing $$m" ; \
                 mkdir -p ${INSTALL_PREFIX}/$$(dirname $$m); \
                 install -p $$m ${INSTALL_PREFIX}/$$m; \
-              fi; \
          fi; \
        done; \
        if [ ! $$do_update ]; then \
                echo "  > All up to date" ; \
-       else \
-               if [ -f "k1om/xeon_phi_multiboot" ] && [ $(BARRELFISH_NFS_DIR)  ]; then \
-                       echo ""; \
-                       echo "Uploading to NFS share $(BARRELFISH_NFS_DIR) ..." ; \
-                       scp k1om/xeon_phi_multiboot $(BARRELFISH_NFS_DIR); \
-                       scp     k1om/sbin/weever $(BARRELFISH_NFS_DIR); \
-               fi; \
        fi; \
        echo ""; \
        echo "done." ; \
@@ -588,35 +576,9 @@ schedsim-check: $(wildcard $(SRCDIR)/tools/schedsim/*.cfg)
 #
 ######################################################################
 
-# we have to filter out the moduels that are generated below
-MODULES_k1om_filtered = $(filter-out xeon_phi_multiboot, \
-                                               $(filter-out sbin/weever,$(MODULES_k1om)))
+k1om/sbin/weever: k1om/sbin/weever_elf
+       $(K1OM_OBJCOPY) -O binary -R .note -R .comment -S k1om/sbin/weever_elf ./k1om/sbin/weever
 
-# Intel Xeon Phi-specific modules
-XEON_PHI_MODULES =\
-       $(foreach m,$(MODULES_COMMON),k1om/$(m)) \
-       $(foreach m,$(MODULES_k1om_filtered),k1om/$(m)) \
-       $(foreach m,$(BENCH_COMMON),k1om/$(m)) \
-       $(foreach m,$(TESTS_COMMON),k1om/$(m)) \
-       $(foreach m,$(BENCH_k1om),k1om/$(m)) \
-       $(foreach m,$(TESTS_k1om),k1om/$(m))
-
-menu.lst.k1om: $(SRCDIR)/hake/menu.lst.k1om
-       cp $< $@
-
-k1om/tools/weever/mbi.c: tools/bin/weever_multiboot \
-                                                k1om/xeon_phi_multiboot \
-                                                k1om/tools/weever/.marker
-       tools/bin/weever_multiboot k1om/multiboot.menu.lst.k1om k1om/tools/weever/mbi.c
-
-k1om/sbin/weever: k1om/sbin/weever.bin tools/bin/weever_creator
-       tools/bin/weever_creator ./k1om/sbin/weever.bin > ./k1om/sbin/weever
-
-k1om/sbin/weever.bin: k1om/sbin/weever_elf
-       $(K1OM_OBJCOPY) -O binary -R .note -R .comment -S k1om/sbin/weever_elf ./k1om/sbin/weever.bin
-
-k1om/xeon_phi_multiboot: $(XEON_PHI_MODULES) menu.lst.k1om
-       $(SRCDIR)/tools/weever/multiboot/build_data_files.sh menu.lst.k1om k1om
 
 
 #######################################################################
index 80efadb..2515cf7 100644 (file)
 
 #define XEON_PHI_MEM_MASK 0xFFFFFFFFFFULL
 
+/**
+ * layout of the boot parameter data structure
+ *
+ * XXX: some fields will be overwritten by the Xeon Phi firmware!
+ */
 struct xeon_phi_boot_params
 {
     uint8_t reserved[0x54];
@@ -107,7 +112,8 @@ struct xeon_phi_boot_params
     uint32_t xeon_phi_id;
     uint64_t msg_base;      /// pointer to the host message base address
     uint8_t msg_size_bits;      /// size of the messaging channel
-    uint64_t multiboot;     /// pointer to the multiboot information
+    //uint64_t multiboot;     /// pointer to the multiboot information
+    uint32_t mbi;
 }__attribute__((packed));
 
 
index aea804f..3af4885 100644 (file)
@@ -158,11 +158,21 @@ static void create_phys_caps(lpaddr_t init_alloc_addr)
     char *mmap_addr = MBADDR_ASSTRING(glbl_core_data->mmap_addr);
     lpaddr_t last_end_addr = 0;
 
-    char *clean_mmap_addr;
-    uint32_t clean_mmap_length;
-    cleanup_bios_regions(mmap_addr, &clean_mmap_addr, &clean_mmap_length);
+    struct multiboot_mmap *mbi_mmaps = (struct multiboot_mmap *)mmap_addr;
+    uint8_t swapped;
+    do {
+        swapped = false;
+        for (uint32_t i = 1; i < glbl_core_data->mmap_length / sizeof(struct multiboot_mmap); ++i) {
+            if (mbi_mmaps[i-1].base_addr > mbi_mmaps[i].base_addr) {
+                struct multiboot_mmap tmp = mbi_mmaps[i-1];
+                mbi_mmaps[i-1] = mbi_mmaps[i];
+                mbi_mmaps[i] = tmp;
+                swapped = true;
+            }
+        }
+    } while(swapped);
 
-    for(char *m = clean_mmap_addr; m < clean_mmap_addr + clean_mmap_length;) {
+    for(char *m = mmap_addr; m < mmap_addr + glbl_core_data->mmap_length;) {
         struct multiboot_mmap *mmap = (struct multiboot_mmap * SAFE)TC(m);
 
         debug(SUBSYS_STARTUP, "MMAP %lx--%lx Type %u\n",
index bbd8015..0134241 100644 (file)
@@ -64,7 +64,6 @@ let arch = "k1om"
                              NoDep SrcTree "src" "/tools/weever",   
                              NoDep BuildTree arch "/include", 
                              NoDep SrcTree "src" "/include/arch/x86_64" ],
-             optDependencies = [Dep BuildTree arch "/tools/weever/mbi.c"],                         
              optDefines = [],
              optLibs = [],
              optLdFlags = [ Str s | s <- [ "-Wl,-N ",
@@ -80,11 +79,9 @@ let arch = "k1om"
              optSuffix = "_for_weever" 
            }
     objs = [ objectFilePath opts f | f <- [ "boot.S", "loader.c", "lib.c", "elf64.c" ] ]
-                ++ [generatedObjectFilePath opts "/tools/weever/mbi.c"]
                                             
 in 
   [ compileCFiles opts [ "loader.c", "lib.c", "elf64.c" ],
-    compileGeneratedCFiles opts ["/tools/weever/mbi.c"],
     assembleSFiles opts [ "boot.S" ],
     link opts objs [] "weever_elf"
   ]
diff --git a/tools/weever/creator/Hakefile b/tools/weever/creator/Hakefile
deleted file mode 100644 (file)
index 02ad8e8..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-----------------------------------------------------------------------
--- Copyright (c) 2009, 2010, ETH Zurich.
--- All rights reserved.
---
--- This file is distributed under the terms in the attached LICENSE file.
--- If you do not find this file, copies can be found by writing to:
--- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
---
--- Hakefile for builder
---
-----------------------------------------------------------------------
-
-[ compileNativeC "weever_creator" ["weever_creator.c"] ["-std=gnu99", "-g"] [] ]
-
diff --git a/tools/weever/creator/weever_creator.c b/tools/weever/creator/weever_creator.c
deleted file mode 100644 (file)
index 9ed0f80..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * \file
- * \brief Builder for the Xeon Phi Bootloader
- */
-
-/*
- * Copyright (c) 2014, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
- */
-
-/*
- * Description
- *
- * This program prepends a >1024 byte header to the Xeon Phi bootloader. The
- * header contains the necessary fields with the information filled in used by
- * the Xeon Phi bootstrap. The header contains the Linux bootinfo struct.
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-/*
- * Size information for the header. The size of the header has to be at
- * least 1024 bytes!
- */
-#define SETUP_SECTORS 2
-#define SECTOR_SIZE 512
-#define HEADER_SIZE (SETUP_SECTORS*SECTOR_SIZE)
-
-unsigned char buf[HEADER_SIZE+1];
-
-int main(int argc, char ** argv)
-{
-    if (argc != 2) {
-        printf("Usage: build setup system > image");
-        return -2;
-    }
-
-    struct stat sb;
-    int fd = open(argv[1], O_RDONLY);
-
-    if (fd < 0 || fstat(fd, &sb)) {
-        printf("Error while opening file\n");
-        return -1;
-    }
-
-    unsigned int sys_size = (sb.st_size + 15) / 16;
-
-    void *kernel = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
-    if (kernel == MAP_FAILED){
-        printf("Error while mapping system\n");
-        return -1;
-    }
-
-    // clear the buffer
-    memset(buf, 0, SETUP_SECTORS * SECTOR_SIZE);
-
-    /*
-     * the following assignments set special values in the bootinfo structure
-     * of the header. The Xeon Phi bootloader reads this value to determine
-     * the size and location of the executable.
-     */
-
-    /*
-     * This is the signature. Without this the kernel does not boot.
-     * Signature is reads "HdrS"
-     */
-    buf[514] = 0x48;
-    buf[515] = 0x64;
-    buf[516] = 0x72;
-    buf[517] = 0x53;
-
-    /*
-     * set the number of setup sectors in addition to the boot sector.
-     * this is SETUP_SECTORS - 1
-     *
-     * Note: Setup must be at least 1024 bytes long to have enough space
-     *       for the boot info struct
-     */
-    buf[0x1f1] = SETUP_SECTORS-1;
-
-    /*
-     * set the size of the bootloader
-     */
-    buf[0x1f4] = sys_size;
-    buf[0x1f5] = sys_size >> 8;
-    buf[0x1f6] = sys_size >> 16;
-    buf[0x1f7] = sys_size >> 24;
-
-    /*
-     * write the filled in header to the file
-     */
-    if (fwrite(buf, 1, HEADER_SIZE, stdout) != HEADER_SIZE) {
-        printf("Writing setup failed");
-        return -1;
-    }
-
-    /*
-     * write the bootloader
-     */
-    if (fwrite(kernel, 1, sb.st_size, stdout) != sb.st_size) {
-        printf("Writing setup failed");
-        return -1;
-    }
-
-    close(fd);
-
-    return 0;
-}
diff --git a/tools/weever/install.sh b/tools/weever/install.sh
deleted file mode 100755 (executable)
index 48f04c1..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-
-
-#
-# \file
-# \brief Boot tool for the Intel Xeon Phi (Linux Host)
-#
-# This program creates a multiboot informaton structure based on the pre-
-# processed menu.lst file
-#
-#
-# Copyright (c) 2014 ETH Zurich.
-# All rights reserved.
-#
-# This file is distributed under the terms in the attached LICENSE file.
-# If you do not find this file, copies can be found by writing to:
-# ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
-#
-
-# stof on error
-set -e
-
-# preparing the upload
-mv multiboot/mbimg ./xeon_phi_multiboot
-rm -rf weever.gz xeon_phi_multiboot.gz
-gzip weever xeon_phi_multiboot
-
-# uploading...
-scp *.gz emmentaler.ethz.ch:
-
-# Issuing commands to emmentaler
-ssh emmentaler.ethz.ch "gunzip -f *.gz"
-ssh emmentaler.ethz.ch "mv weever /home/netos/tftpboot/acreto/"
-ssh emmentaler.ethz.ch "mv xeon_phi_multiboot /home/netos/tftpboot/acreto"
-
index 1ddd3d9..8d932c3 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <xeon_phi/xeon_phi.h>
 
-#include "mbi.h"
 
 #include "../../kernel/include/multiboot.h"
 
@@ -203,44 +202,15 @@ loader(uint64_t magic,
         eabort('E', 'a');
     }
 
-    multiboot_info = get_multiboot();
-
     print_status('S', '1');
 
     /*
-     * Copy the multiboot image closer to the kernel
+     * XXX: copying the boot loader information structure around
      */
-    lpaddr_t mb_img_start = ROUND_UP((lpaddr_t )&_end_bootloader, BASE_PAGE_SIZE)
-            ;
-    if (mb_img_start + bp->cmdline_size > bp->cmdline_ptr) {
-        eabort('E', '1');
-    }
-    memcpy((void *) mb_img_start, (void *) (uintptr_t)bp->cmdline_ptr, bp->cmdline_size);
-    bp->cmdline_ptr = mb_img_start;
-
-    mb_img_start = ROUND_UP(mb_img_start+bp->cmdline_size, 1<<20);
-    lpaddr_t mb_img_orig = bp->ramdisk_image;
-    if (mb_img_start + bp->ramdisk_size > bp->ramdisk_image) {
-        mb_img_orig = bp->ramdisk_image + bp->ramdisk_size + BASE_PAGE_SIZE;
-        memcpy((void *) mb_img_orig, (void *)(uintptr_t) bp->ramdisk_image, bp->ramdisk_size);
-        print_status('C', '1');
-    }
 
-    memcpy((void *) mb_img_start, (void *) mb_img_orig, bp->ramdisk_size);
 
-    bp->ramdisk_image = mb_img_start;
-    /*
-     * the multiboot does only stores the offsets within the multiboot image
-     * thus we have to adjust the addresses in the multiboot info struct
-     */
-    struct multiboot_modinfo *mod;
-    mod = (struct multiboot_modinfo *) (uintptr_t) multiboot_info->mods_addr;
+    multiboot_info = (struct multiboot_info *)(uint64_t)bp->mbi;
 
-    for (size_t i = 0; i < multiboot_info->mods_count; i++) {
-        mod->mod_start += mb_img_start;
-        mod->mod_end += mb_img_start;
-        mod++;
-    }
     print_status('S', '2');
 
     /* look up the kernel module */
@@ -254,11 +224,9 @@ loader(uint64_t magic,
     }
 
     /* set the start address where we can allocate ram */
-    phys_alloc_start = ROUND_UP(mb_img_start + bp->ramdisk_size,
+    phys_alloc_start = ROUND_UP(bp->ramdisk_image + bp->ramdisk_size,
                                 BASE_PAGE_SIZE)+BASE_PAGE_SIZE;
 
-    bp->ramdisk_image = (uint32_t) mb_img_start;
-
     lpaddr_t kernel_start = phys_alloc_start;
 
     /* overwrite the cmd line with the one supplied by the host */
diff --git a/tools/weever/mbi.h b/tools/weever/mbi.h
deleted file mode 100644 (file)
index a0a0b4d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * \file
- * \brief Struct definition for the boot param struct supplied by the
- *        K1OM boot loader
- */
-
-/*
- * Copyright (c) 2013 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
- */
-#ifndef MBI_H_
-#define MBI_H_
-
-struct multiboot_info *get_multiboot(void);
-
-#endif /* MBI_H_ */
diff --git a/tools/weever/multiboot/Hakefile b/tools/weever/multiboot/Hakefile
deleted file mode 100644 (file)
index 2aa24c0..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-----------------------------------------------------------------------
--- Copyright (c) 2009, 2010, ETH Zurich.
--- All rights reserved.
---
--- This file is distributed under the terms in the attached LICENSE file.
--- If you do not find this file, copies can be found by writing to:
--- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
---
--- Hakefile for xloader
---
-----------------------------------------------------------------------
-
-[ compileNativeC "weever_multiboot" ["weever_multiboot.c"] ["-std=gnu99", "-g"] [] ]
-
diff --git a/tools/weever/multiboot/build_data_files.sh b/tools/weever/multiboot/build_data_files.sh
deleted file mode 100755 (executable)
index b9d5be6..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/bin/bash
-
-#
-# \file
-# \brief Multiboot information creator
-#
-# This program creates a multiboot informaton structure based on the pre-
-# processed menu.lst file
-#
-#
-# Copyright (c) 2014 ETH Zurich.
-# All rights reserved.
-#
-# This file is distributed under the terms in the attached LICENSE file.
-# If you do not find this file, copies can be found by writing to:
-# ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
-#
-
-# abort on any errors as this produces invalid images
-set -e
-
-if [ $# != 2 ]; then
-    echo Expected $0 menu.lst output_prefix
-
-    exit 1
-fi
-
-ALIGNMENT=4096
-
-MENU_LST=$1
-OUTPUT_PREFIX=$2
-
-ALIGNMENT=4096
-
-# Prefix prepended to each output file within the directory
-# $OUTPUT_PREFIX (for safety, this means we can clean the directory
-# by removing everything with this prefix)
-FILE_PREFIX=multiboot
-
-MBIMG=$OUTPUT_PREFIX/xeon_phi_multiboot
-MBHEADER=$OUTPUT_PREFIX/${FILE_PREFIX}.$MENU_LST
-
-# Set up output direcotry
-if [ -e $OUTPUT_PREFIX  ] && [ ! -d $OUTPUT_PREFIX ]; then
-    echo "  !Error: $OUTPUT_PREFIX exists, but is not a directory"
-    exit 1
-fi
-
-if [ ! -d $OUTPUT_PREFIX/ ]; then
-    echo "  Making output directory $OUTPUT_PREFIX"
-    mkdir $OUTPUT_PREFIX
-fi
-
-
-rm -f $MBIMG
-rm -f $MBHEADER
-
-# Get list of binaries to translate
-
-
-OFFSET=0
-
-
-echo -n "Start parsing multiboot... "
-while read line           
-do           
-  # remove leading spaces
-  MBMOD=$(echo $line | sed 's/^ *//')
-  TYPE=$(echo $MBMOD | cut -f1 -d ' ')
-  
-  if [[ "$TYPE" == "#" ]]; then
-    continue
-  fi
-  
-
-  if [[ "$TYPE" == "mmap" ]]; then
-    echo $line >> $MBHEADER
-    continue
-  fi
-
-  if [[ "$TYPE" == "module" ]] || [[ "$TYPE" == "kernel" ]]; then
-    BIN=$(echo $MBMOD | cut -f2 -d ' ')
-    CMD=$(echo $MBMOD | cut -f3-99 -d ' ')
-  
-    FILESIZE=$(stat -c%s ".$BIN")
-    PADDING=$(echo "($ALIGNMENT-($FILESIZE%$ALIGNMENT))" | bc)  
-#    echo '   +'$BIN ': Size='$FILESIZE', Padding Size='$PADDING' , Offset='$OFFSET
-    cat "."$BIN >>  $MBIMG
-    for ((i=0; i < $PADDING; i=i+1)) do
-       echo -en "\0" >> $MBIMG
-    done
-    echo $TYPE" "$BIN" "$OFFSET" "$FILESIZE" "$CMD >> $MBHEADER
-    OFFSET=$(echo "$OFFSET+$PADDING+$FILESIZE" | bc)
-  fi
-done <$MENU_LST        
-
-echo "done."
diff --git a/tools/weever/multiboot/weever_multiboot.c b/tools/weever/multiboot/weever_multiboot.c
deleted file mode 100644 (file)
index 4ae4345..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/**
- * \file
- * \brief Multiboot information creator
- *
- * This program creates a multiboot informaton structure based on the pre-
- * processed menu.lst file
- */
-
-/*
- * Copyright (c) 2014 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include "elf.h"
-
-#define MAX_LINE_SIZE 2048
-#define MAX_CMD_SIZE 64
-#define MAX_ARGS_SIZE 1024
-#define MAX_IMAGE_SIZE 256
-
-#define MAX_MODULES 256
-
-static char *kernel_cmd_line;
-static unsigned int kernel_offset;
-static unsigned int kernel_length;
-static unsigned int module_offset[MAX_MODULES];
-static unsigned int module_length[MAX_MODULES];
-static char *module_cmd_line[MAX_MODULES];
-
-
-int
-main(int argc,
-     char *argv[])
-{
-    int n_modules = 0;
-    int n_mmaps = 0;
-
-    if (argc < 3) {
-        printf("Usage: %s <menu.lst> <output.c>\n", argv[0]);
-        return 0;
-    }
-
-    FILE *f = fopen(argv[1], "r");
-    assert((f != NULL) && "Could not open input file");
-
-    FILE *o = fopen(argv[2], "w");
-    assert((o != NULL) && "Could not open output file");
-
-    // Output initial part of file: include basic types etc.
-    fprintf(o, "#include <assert.h>\n");
-    fprintf(o, "#include <stdio.h>\n");
-    fprintf(o, "#include <stdint.h>\n");
-    fprintf(o, "#include <stddef.h>\n");
-    fprintf(o, "#include <string.h>\n");
-    fprintf(o, "#include <barrelfish_kpi/types.h>\n");
-    fprintf(o, "#include <errors/errno.h>\n");
-    fprintf(o, "#include <elf/elf.h>\n");
-    fprintf(o, "#include \"mbi.h\"\n");
-    fprintf(o, "#include \"../kernel/include/multiboot.h\"\n");
-
-    // Process menu.lst, generating definitions
-    uint64_t offset;
-    uint64_t length;
-
-    char cmd[MAX_CMD_SIZE], args[MAX_ARGS_SIZE], image[MAX_IMAGE_SIZE];
-    while (!feof(f)) {
-        char line[MAX_LINE_SIZE], *l;
-
-        cmd[0] = args[0] = image[0] = line[0] = '\0';
-
-        /*
-         * input format
-         *
-         * CMD    IMAGE          OFFSET SIZE ARGS
-         * kernel /k1om/sbin/cpu 0 1006840 loglevel=4
-         *
-         */
-        l = fgets(line, MAX_LINE_SIZE, f);
-        if (!l) {
-            /* error or EOF, check for EOF with next iteration */
-            continue;
-        }
-        sscanf(line, "%s %s %lu %lu %[^\n]", cmd, image, &offset, &length, args);
-
-        if (!strcmp(cmd, "kernel")) {
-            printf("   +Kernel: %s, offset=0x%lx, length=0x%lx, args=%s\n",
-                   image, offset, length, args);
-            kernel_cmd_line = malloc(strlen(line) + 1);
-            kernel_length = length;
-            kernel_offset = offset;
-            sprintf(kernel_cmd_line, "%s %s", image, args);
-        } else if (!strcmp(cmd, "module")) {
-            assert(n_modules < MAX_MODULES);
-            module_cmd_line[n_modules] = malloc(strlen(line) + 1);
-            module_length[n_modules] = length;
-            module_offset[n_modules] = offset;
-            sprintf(module_cmd_line[n_modules], "%s %s", image, args);
-            printf("   +Module [%d]: %s, offset=0x%lx, length=0x%lx, args=%s\n", n_modules,
-                               image, offset, length, args);
-            n_modules++;
-        } else if (!strcmp(cmd, "mmap")) {
-            //uint64_t base, len;
-            int type;
-            sscanf(line, "%s %s %lx %lx %i", cmd, image, &offset, &length, &type);
-            sscanf(args, "%i", &type);
-            printf("   +MMAP %d: [0x%" PRIx64 ", 0x%" PRIx64 "], type %d\n",
-                   n_mmaps, offset, length, type);
-            fprintf(o, "static uint64_t mbi_mmap%d[] = {0x%lx, 0x%lx, %d};\n",
-                    n_mmaps, offset, length, type);
-            n_mmaps++;
-        } else {
-            bool iscmd = false;
-            for (int i = 0; i < strlen(cmd); i++) {
-                if (cmd[i] == '#') {
-                    break;
-                }
-                if (!isspace(cmd[i])) {
-                    iscmd = true;
-                    break;
-                }
-            }
-            if (iscmd) {
-                printf("   -Ignoring command '%s'\n", cmd);
-            }
-        }
-    }
-
-    // Generate multiboot-structure initialization code
-    fprintf(o, "static struct multiboot_modinfo mbi_mods[%d];\n", n_modules + 1);
-    fprintf(o, "static struct multiboot_mmap mbi_mmaps[%d];\n", n_mmaps);
-    fprintf(o, "static struct multiboot_info mbi;\n\n");
-    fprintf(o, "struct multiboot_info *get_multiboot(void) {\n");
-
-    // Flags:
-    fprintf(o, "  mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_CMDLINE;\n");
-    fprintf(o, "  mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_MODS;\n");
-    fprintf(o, "  mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_ELF_SYMS;\n");
-    fprintf(o, "  mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_MMAP;\n");
-
-    // Kernel command line:
-    fprintf(o, "  mbi.cmdline = (uint32_t)(uint64_t) \"%s\";\n", kernel_cmd_line);
-
-    // Modules:
-    fprintf(o, "  mbi.mods_count = %d;\n", n_modules + 1);
-    fprintf(o, "  mbi.mods_addr = (uint32_t)(uint64_t) mbi_mods;\n");
-    fprintf(o, "  mbi_mods[0].mod_start = (uint32_t) 0x%x;\n", kernel_offset);
-    fprintf(o, "  mbi_mods[0].mod_end = (uint32_t) 0x%x;\n",
-            kernel_offset + kernel_length);
-    fprintf(o, "  mbi_mods[0].string = (uint32_t)(uint64_t) \"%s\";\n",
-            kernel_cmd_line);
-
-    for (int i = 0; i < n_modules; i++) {
-        fprintf(o, "  mbi_mods[%d].mod_start = (uint32_t) 0x%x;\n", i + 1,
-                module_offset[i]);
-        fprintf(o, "  mbi_mods[%d].mod_end = (uint32_t) 0x%x;\n", i + 1,
-                module_offset[i] + module_length[i]);
-        fprintf(o, "  mbi_mods[%d].string = (uint32_t)(uint64_t) \"%s\";\n", i + 1,
-                module_cmd_line[i]);
-    }
-
-    // MMAPS:
-    fprintf(o, "  mbi.mmap_length = sizeof(mbi_mmaps);\n");
-    fprintf(o, "  mbi.mmap_addr = (uint32_t)(uint64_t) mbi_mmaps;\n");
-    for (int i = 0; i < n_mmaps; i++) {
-        fprintf(o, "  mbi_mmaps[%d].size = sizeof(struct multiboot_mmap);\n", i);
-        fprintf(o, "  mbi_mmaps[%d].base_addr = mbi_mmap%d[0];\n", i, i);
-        fprintf(o, "  mbi_mmaps[%d].length = mbi_mmap%d[1];\n", i, i);
-        fprintf(o, "  mbi_mmaps[%d].type = (int)mbi_mmap%d[2];\n", i, i);
-    }
-    fprintf(o, "  return &mbi;\n");
-    fprintf(o, "}\n\n");
-
-    fclose(f);
-    fclose(o);
-
-    return 0;
-}
index 428db50..b4773cf 100644 (file)
@@ -42,7 +42,8 @@
       "xeon_phi_manager_client",
       "xeon_phi_client",
       "octopus",
-      "mm"
+      "mm",
+      "tftp_client"
     ],
     flounderDefs = [
       "interphi", 
index 0cc051a..29f0cb0 100644 (file)
 
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
+
 #include <barrelfish/barrelfish.h>
 #include <spawndomain/spawndomain.h>
 #include <vfs/vfs.h>
 #include <elf/elf.h>
 
 #include <xeon_phi/xeon_phi.h>
+#include <tftp/tftp.h>
+
+#include <../kernel/include/multiboot.h>
 
 #include <dev/xeon_phi/xeon_phi_boot_dev.h>
 #include <dev/xeon_phi/xeon_phi_apic_dev.h>
@@ -32,6 +37,11 @@ struct bootinfo *bi = NULL;
 #include "interphi.h"
 #include "sleep.h"
 
+#define TFTP_BUF_SIZE (1<<20)
+#define TFTP_BUF_SIZE_MODULES (1<<30)
+
+typedef errval_t (*loadfile_fn_t)(char *path, void *buf, size_t buflen, size_t *ret_size);
+
 #define BOOT_TIMEOUT 3000
 #define BOOT_COUNTER 0xFFFFF
 
@@ -85,271 +95,549 @@ static uint64_t get_adapter_memsize(void)
     }
 }
 
+/**
+ * \brief   generates the cmdline supplied to the card kernel
+ *
+ * \param   phi         the card information structure
+ * \param   load_offset offset where to load the cmdline
+ * \param   ret_size    size of the cmdline in bytes
+ */
+static errval_t load_cmdline(struct xeon_phi *phi, lvaddr_t load_offset)
+{
+    uint32_t cmdlen = 0;
+
+    struct xeon_phi_boot_params *bp;
+    bp = (struct xeon_phi_boot_params *)(phi->apt.vbase + phi->os_offset);
+
+    void *buf = (void *) (phi->apt.vbase + load_offset);
+
+    if (phi->cmdline) {
+        cmdlen += sprintf(buf + cmdlen, "%s", phi->cmdline);
+    }
+
+    cmdlen += sprintf(buf + cmdlen, "card_id=%i", phi->id);
+
+    /*
+     * id
+     */
+    /*
+     * TODO: Add multihop / communication information here..
+     */
+
+    XBOOT_DEBUG("cmdline @ 0x%" PRIx32 " '%s'\n", (uint32_t)load_offset, (char*)buf);
+
+    phi->cmdline = buf;
+    phi->cmdlen = cmdlen;
+
+
+    bp->cmdline_ptr = (uint32_t)(load_offset);
+    bp->cmdline_size = (uint32_t)cmdlen;
+
+    return SYS_ERR_OK;
+}
+
+static errval_t bootstrap_notify(struct xeon_phi *phi)
+{
+    // set the bootimage size to tell the bootloader
+    xeon_phi_boot_os_size_rawwr(&boot_registers, phi->os_size);
+
+    uint64_t memsize = get_adapter_memsize();
+
+    uint64_t reserved = (memsize * MEMORY_RESERVE_PERCENT / 100);
+
+    // Keep in mind maximum uos reserve size is uint32_t, so we never overflow
+    reserved = MIN(reserved, UOS_RESERVE_SIZE_MAX);
+    reserved = MAX(reserved, UOS_RESERVE_SIZE_MIN);
+
+    // Always align uos reserve size to a page
+    reserved = (reserved & ~(BASE_PAGE_SIZE - 1));
+
+    xeon_phi_boot_res_size_rawwr(&boot_registers, (uint32_t) reserved);
+
+    // sending the bootstrap interrupt
+    xeon_phi_apic_icr_lo_t icr_lo = xeon_phi_apic_icr_lo_default;
+    icr_lo = xeon_phi_apic_icr_lo_vector_insert(icr_lo, xeon_phi_apic_vec_bsp);
+    icr_lo = xeon_phi_apic_icr_lo_boot_notify_insert(icr_lo, 0x1);
+
+    assert(icr_lo == (229 | (1 << 13)));
+
+    xeon_phi_apic_icr_hi_wr(&apic_registers, xeon_phi_apic_bootstrap, phi->apicid);
+
+    xeon_phi_apic_icr_lo_wr(&apic_registers, xeon_phi_apic_bootstrap, icr_lo);
+
+    return SYS_ERR_OK;
+}
+
+/*
+ * -------------------------------------------------------------------------------
+ * VFS helper function
+ * -------------------------------------------------------------------------------
+ */
 
-static errval_t load_module(char *path,
-                            uint8_t use_nfs,
-                            void *buf,
-                            uint64_t *ret_size)
+static vfs_handle_t file_open(char *file, uint8_t nfs)
 {
     errval_t err;
 
-    char *mod_path = path;
-    if (use_nfs) {
-        size_t path_size = strlen(path) + strlen(XEON_PHI_NFS_MNT) + 2;
-        mod_path = malloc(path_size);
-        if (mod_path == NULL) {
-            return LIB_ERR_MALLOC_FAIL;
+    vfs_handle_t fh;
+    char *path = file;
+    if (nfs) {
+        size_t path_size = strlen(file) + strlen(XEON_PHI_NFS_MNT) + 2;
+        path = malloc(path_size);
+        if (path == NULL) {
+            return NULL;
         }
-        if (path[0] == '/') {
-            snprintf(mod_path, path_size, "%s%s", XEON_PHI_NFS_MNT, path);
+        if (file[0] == '/') {
+            snprintf(path, path_size, "%s%s", XEON_PHI_NFS_MNT, file);
         } else {
-            snprintf(mod_path, path_size, "%s/%s", XEON_PHI_NFS_MNT, path);
+            snprintf(path, path_size, "%s/%s", XEON_PHI_NFS_MNT, file);
         }
     }
 
-
-    /* read file into memory */
-    vfs_handle_t fh;
-    err = vfs_open(mod_path, &fh);
-    if (err_is_fail(err)) {
-        return err_push(err, SPAWN_ERR_LOAD);
+    err = vfs_open(path, &fh);
+    if (nfs) {
+        free(path);
     }
-
-    struct vfs_fileinfo info;
-    err = vfs_stat(fh, &info);
-    if (err_is_fail(err)) {
-        vfs_close(fh);
-        return err_push(err, SPAWN_ERR_LOAD);
+    switch(err_no(err)) {
+        case SYS_ERR_OK :
+            return fh;
+            break;
+        case FS_ERR_NOTFOUND :
+            err = vfs_open(file, &fh);
+            if (err_is_ok(err)) {
+                return fh;
+            }
+            return NULL;
+            break;
+        default:
+            return NULL;
     }
 
-    assert(info.type == VFS_FILE);
-
-    uint8_t *image = buf;
+    return NULL;
+}
 
-    size_t pos = 0, readlen;
+static errval_t file_load(vfs_handle_t fh, void *buf, size_t length)
+{
+    errval_t err;
+    size_t pos = 0, readlen = 0;
     do {
-        err = vfs_read(fh, &image[pos], info.size - pos, &readlen);
+        err = vfs_read(fh, buf+pos, length - pos, &readlen);
         if (err_is_fail(err)) {
-            vfs_close(fh);
-            return err_push(err, SPAWN_ERR_LOAD);
+            return err;
         } else if (readlen == 0) {
-            vfs_close(fh);
             return SPAWN_ERR_LOAD; // XXX
         } else {
             pos += readlen;
         }
-    } while (err_is_ok(err) && readlen > 0 && pos < info.size);
-
-    err = vfs_close(fh);
-    if (err_is_fail(err)) {
-        DEBUG_ERR(err, "failed to close file %s", path);
-    }
-
-    if (ret_size) {
-        *ret_size = info.size;
-    }
+    } while (err_is_ok(err) && readlen > 0 && pos < length);
 
     return SYS_ERR_OK;
-
 }
 
-/**
- * \brief Loads the bootloader image onto the card
- *
- * \param phi           the xeon phi card information
- * \param xloader_img   name of the bootloader image
- * \param ret_imgsize   returned image size
- *
- * Note: it is important that the bootloader just uses statically allocated
- *       memory and does not exceed its image size with additional memory.
- *       Otherwise the CMD line or the multiboot image will be overwritten.
- */
-static errval_t load_bootloader(struct xeon_phi *phi,
-                                char *xloader_img)
+
+static errval_t download_file_vfs(char *file, void *card_buffer, size_t use_nfs,
+                                  size_t *bytes)
 {
     errval_t err;
-#if 0
-    /*
-     * find the boot loader image in the host multiboot
-     */
-    struct mem_region *module = multiboot_find_module(bi, xloader_img);
-    if (module == NULL) {
-        return SPAWN_ERR_FIND_MODULE;
-    }
 
-    lvaddr_t binary = 0;
-    size_t imgsize = 0;
+    vfs_handle_t fh = file_open(file, use_nfs);
+    if (fh == NULL) {
+        return FS_ERR_INVALID_FH;
+    }
 
-    err = spawn_map_module(module, &imgsize, &binary, NULL);
+    struct vfs_fileinfo info;
+    err = vfs_stat(fh, &info);
     if (err_is_fail(err)) {
-        return err_push(err, SPAWN_ERR_ELF_MAP);
+        goto out;
     }
 
-    imgsize = module->mrmod_size;
+    if (bytes) {
+        *bytes = info.size;
+    }
 
+    assert(info.type == VFS_FILE);
+    assert(info.size < 4UL<<30);
 
+    err = file_load(fh, card_buffer, info.size);
+    out:
+    vfs_close(fh);
+    return err;
+}
 
-    /*
-     * get the load offset: we do not want to write into the boot loade
-     */
-    lvaddr_t loadoffset = get_load_offset(phi);
+/*
+ * -------------------------------------------------------------------------------
+ * boot loader
+ * -------------------------------------------------------------------------------
+ */
 
-    get_adapter_memsize();
+#define SETUP_SECTORS 2
+#define SECTOR_SIZE 512
+#define HEADER_SIZE (SETUP_SECTORS*SECTOR_SIZE)
 
-    phi->apicid = xeon_phi_boot_download_apicid_rdf(&boot_registers);
+static errval_t download_bootloader_generic(struct xeon_phi *phi, char *bootloader,
+                                            loadfile_fn_t loadfn, size_t args)
+{
+    errval_t err;
 
-    XBOOT_DEBUG("Loading xloader onto card... offset = 0x%lx\n", loadoffset);
+    lvaddr_t loadoffset = get_load_offset(phi);
+    size_t imgsize;
 
-    memcpy((void *) (phi->apt.vbase + loadoffset), (void *) binary, imgsize);
+    char *buf = (void *) (phi->apt.vbase + loadoffset);
 
-#endif
-    lvaddr_t loadoffset = get_load_offset(phi);
-    uint64_t imgsize;
+    /* fill in the header */
+    memset(buf, 0, HEADER_SIZE);
 
-    void *buf = (void *) (phi->apt.vbase + loadoffset);
+    /*
+     * This is the signature. Without this the kernel does not boot.
+     * Signature is reads "HdrS"
+     */
+    buf[514] = 0x48;
+    buf[515] = 0x64;
+    buf[516] = 0x72;
+    buf[517] = 0x53;
+    buf[0x1f1] = SETUP_SECTORS-1;
 
-    err = load_module(xloader_img, phi->use_nfs, buf, &imgsize);
+    err = loadfn(bootloader, buf + HEADER_SIZE, args, &imgsize);
     if (err_is_fail(err)) {
         return err;
     }
 
+    size_t sys_size = (imgsize + 15) / 16;
+    buf[0x1f4] = sys_size;
+    buf[0x1f5] = sys_size >> 8;
+    buf[0x1f6] = sys_size >> 16;
+    buf[0x1f7] = sys_size >> 24;
+
     phi->apicid = xeon_phi_boot_download_apicid_rdf(&boot_registers);
 
     phi->os_offset = loadoffset;
     phi->os_size = imgsize;
 
+    XBOOT_DEBUG("Xeon Phi bootloader %s loaded @ 0x%lx size %lu kB\n", bootloader,
+                loadoffset, imgsize >> 10);
+
     return SYS_ERR_OK;
 }
 
-/**
- *
+
+static inline errval_t download_bootloader_vfs(struct xeon_phi *phi, char *bootloader,
+                                               uint8_t use_nfs)
+{
+   return download_bootloader_generic(phi, bootloader, download_file_vfs, use_nfs);
+}
+
+static inline errval_t download_bootloader_tftp(struct xeon_phi *phi, char *bootloader)
+{
+    return download_bootloader_generic(phi, bootloader, tftp_client_read_file,
+                                       TFTP_BUF_SIZE_MODULES);
+}
+
+
+/*
+ * -------------------------------------------------------------------------------
+ * multiboot modules
+ * -------------------------------------------------------------------------------
  */
-static errval_t load_multiboot_image(struct xeon_phi *phi,
-                                     char *multiboot_img,
-                                     lvaddr_t load_offset)
+
+static uint32_t prepare_multiboot_strings(void *strings, char **mods,
+                                          uint32_t num_mods)
 {
-    errval_t err;
+    uint32_t bytes = 0;
+    for (uint32_t i = 0; i < num_mods; ++i) {
+        bytes += snprintf(strings+bytes, 1<<20, "%s", mods[i]) + 1;
+    }
+    return bytes;
+}
 
-    assert(phi->os_offset != 0);
+static inline char *get_module_path(char *cmdline)
+{
+    while(*cmdline) {
+        if (isspace((int)*cmdline)) {
+            return cmdline;
+        }
+        cmdline++;
+    }
+    return cmdline;
+}
 
-#if 0
+static uint32_t prepare_multiboot_info(void *aptvbase, lpaddr_t offset,
+                                       char **mmaps, uint32_t num_mods,
+                                       uint32_t num_mmaps)
+{
+    void *mbibuf = aptvbase + offset;
     /*
-     * find the boot loader image in the host multiboot
+     * Layout of multi boot information on card:
+     * [multiboot_info]
+     * [n x multiboot_modinfo]
+     * [m x multiboot_mmap]
+     * [strings]
      */
-    struct mem_region *module = multiboot_find_module(bi, multiboot_img);
-    if (module == NULL) {
-        return SPAWN_ERR_FIND_MODULE;
+
+    /* set the host virtual pointers of the multiboot structures */
+    struct multiboot_info *mbi = mbibuf;
+    struct multiboot_modinfo *mbi_mods = (struct multiboot_modinfo *)(mbi + 1);
+    struct multiboot_mmap *mbi_mmaps = (struct multiboot_mmap *)(mbi_mods + num_mods);
+
+    /* card physical modules array */
+    offset += (uint32_t)sizeof(struct multiboot_info);
+    mbi->mods_count = num_mods;
+    mbi->mods_addr = offset;
+
+    /* card physical mmap array */
+    offset += num_mods * (uint32_t)sizeof(struct multiboot_modinfo);
+    mbi->mmap_addr = offset;
+    mbi->mmap_length = num_mmaps * sizeof(struct multiboot_mmap);
+
+    offset += num_mmaps * (uint32_t)sizeof(struct multiboot_mmap);
+
+    /* set the multiboot flags */
+    mbi->flags = MULTIBOOT_INFO_FLAG_HAS_CMDLINE | MULTIBOOT_INFO_FLAG_HAS_MODS
+                    | MULTIBOOT_INFO_FLAG_HAS_ELF_SYMS| MULTIBOOT_INFO_FLAG_HAS_MMAP;
+
+    for (uint32_t i = 0; i < num_mmaps; ++i) {
+        uint32_t parsed = sscanf(mmaps[i],"map%*[ \n\t]%" SCNx64
+                                 "%*[ \n\t]%" SCNx64 "%*[ \n\t]%" SCNu32,
+                                 &mbi_mmaps[i].base_addr,
+                                 &mbi_mmaps[i].length,
+                                 &mbi_mmaps[i].type);
+        if (parsed !=3) {
+            debug_printf("INVALID mmap: {%s}\n", mmaps[i]);
+            mbi_mmaps[i].size = 0;
+            continue;
+        }
+        mbi_mmaps[i].size = sizeof(struct multiboot_mmap);
     }
 
-    lvaddr_t image = 0;
-    size_t imgsize = 0;
+    return sizeof(*mbi) + num_mods * sizeof(*mbi_mods) + num_mmaps * sizeof(*mbi_mmaps);
+}
 
-    err = spawn_map_module(module, &imgsize, &image, NULL);
-    if (err_is_fail(err)) {
-        return err_push(err, SPAWN_ERR_ELF_MAP);
-    }
+static errval_t download_modules_generic(struct xeon_phi *phi, size_t offset,
+                                         char **mods, uint32_t num_mods,
+                                         uint32_t num_mmaps, loadfile_fn_t loadfn,
+                                         size_t args)
+{
+    errval_t err;
 
-    imgsize = module->mrmod_size;
+    struct xeon_phi_boot_params *bp;
+    bp = (struct xeon_phi_boot_params *)(phi->apt.vbase + phi->os_offset);
 
-    XBOOT_DEBUG("loading multiboot image onto card... offset = 0x%lx\n",
-                load_offset);
+    struct multiboot_info *mbi = (void *)phi->apt.vbase + offset;
+    struct multiboot_modinfo *mbi_mods = (struct multiboot_modinfo *)(mbi + 1);
 
-    memcpy((void *) (phi->apt.vbase + load_offset), (void *) image, imgsize);
-#endif
+    bp->ramdisk_image = offset;
+    bp->mbi = offset;
 
-    uint64_t imgsize;
+    offset += prepare_multiboot_info((void *)phi->apt.vbase, offset, mods + num_mods,
+                                     num_mods, num_mmaps);
 
-    void *buf = (void *) (phi->apt.vbase + load_offset);
+    lpaddr_t strings_offset = offset;
+    offset += prepare_multiboot_strings((void *)phi->apt.vbase + strings_offset,
+                                        mods, num_mods);
 
-    err = load_module(multiboot_img, phi->use_nfs, buf, &imgsize);
-    if (err_is_fail(err)) {
-        return err;
+    offset = ALIGN(offset);
+
+    for (uint32_t i = 0; i < num_mods; ++i) {
+        char *strings = (void *)phi->apt.vbase + strings_offset;
+        size_t cmdlength = strlen(strings);
+        size_t imgsize = 0;
+        mbi_mods[i].mod_start = offset;
+        mbi_mods[i].string = strings_offset;
+
+        char *delim = get_module_path(mods[i]);
+        *delim = 0;
+
+        err = loadfn(mods[i], (void *)phi->apt.vbase + offset, args, &imgsize);
+        if (err_is_fail(err)) {
+            return err;
+        }
+        mbi_mods[i].mod_end = mbi_mods[i].mod_start + imgsize;
+
+        offset = ALIGN(offset + imgsize);
+        strings_offset += (cmdlength + 1);
+
+        XBOOT_DEBUG("module %30s @ 0x08%lx  size %lu kB\n",
+                    (char *)phi->apt.vbase + strings_offset, offset, imgsize >> 10);
     }
 
-    /*
-     * we are using the Linux style way in booting. The following will update
-     * the corresponding fields in struct boot_param of the header.
-     */
-    struct xeon_phi_boot_params *bp;
-    bp = (struct xeon_phi_boot_params *)(phi->apt.vbase + phi->os_offset);
-    bp->ramdisk_image = (uint32_t)load_offset;
-    bp->ramdisk_size = (uint32_t)imgsize;
+    bp->ramdisk_size = offset - bp->ramdisk_image;
 
     return SYS_ERR_OK;
 }
 
-/**
- * \brief   generates the cmdline supplied to the card kernel
- *
- * \param   phi         the card information structure
- * \param   load_offset offset where to load the cmdline
- * \param   ret_size    size of the cmdline in bytes
+
+static errval_t download_modules_vfs(struct xeon_phi *phi, size_t offset,
+                                     char **mods, uint32_t num_mods,
+                                     uint32_t num_mmaps, uint8_t use_nfs)
+{
+    return download_modules_generic(phi, offset, mods, num_mods, num_mmaps,
+                                    download_file_vfs, use_nfs);
+}
+
+static errval_t download_modules_tftp(struct xeon_phi *phi, lpaddr_t offset,
+                                      char **mods, uint32_t num_mods,
+                                      uint32_t num_mmaps)
+{
+    return download_modules_generic(phi, offset, mods, num_mods, num_mmaps,
+                                    tftp_client_read_file, TFTP_BUF_SIZE_MODULES);
+}
+
+/*
+ * -------------------------------------------------------------------------------
+ * Parsing modules
+ * -------------------------------------------------------------------------------
  */
-static errval_t load_cmdline(struct xeon_phi *phi,
-                             lvaddr_t load_offset)
+
+static inline char *discard_leading_white_spaces(char *string)
 {
-    uint32_t cmdlen = 0;
+    while(*string) {
+        if (!isspace((int)*string)) {
+            break;
+        }
+        string++;
+    }
+    return string;
+}
 
-    struct xeon_phi_boot_params *bp;
-    bp = (struct xeon_phi_boot_params *)(phi->apt.vbase + phi->os_offset);
 
-    XBOOT_DEBUG("copying cmdline onto card, offset = 0x%lx\n", load_offset);
+static errval_t parse_mod_list(char *modules, uint32_t *mods, uint32_t *mmaps,
+                               uint8_t *kernel, char ***parsed_modules)
+{
+    uint32_t num_mod = 0, num_mmap = 0;
+    uint8_t has_kernel = 0;
 
-    void *buf = (void *) (phi->apt.vbase + load_offset);
+    char *line = modules;
 
-    if (phi->cmdline) {
-        cmdlen += sprintf(buf + cmdlen, "%s", phi->cmdline);
+    /* how many modules we have */
+    while (line != NULL)
+    {
+        if (*line == '\n') {
+            line++;
+        }
+        if (strncmp(line, "module", 6)==0) {
+            num_mod ++;
+        } else if (strncmp(line, "kernel", 6) == 0) {
+            assert(has_kernel == 0);
+            has_kernel = 1;
+        } else if (strncmp(line, "mmap", 4) == 0) {
+            num_mmap++;
+        }
+        line=strchr(line+1,'\n');
     }
 
-    cmdlen += sprintf(buf + cmdlen, "card_id=%i", phi->id);
 
-    /*
-     * id
-     */
-    /*
-     * TODO: Add multihop / communication information here..
-     */
+    /* allocate parsed array */
+    char **parsed = calloc(num_mod + num_mmap + 1, sizeof(char *));
+    if (parsed == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
 
-    printf("cmdline = %x,  %s\n", (uint32_t)load_offset, (char*)buf);
+    uint32_t mod_idx = 1;
+    uint32_t mmap_idx = num_mod + num_mmap;
+    line = modules;
+    while (line != NULL)
+    {
+        if (*line == '\n') {
+            *line = 0;
+            line++;
+        }
+        if (strncmp(line, "module", 6)==0) {
+            parsed[mod_idx++] = discard_leading_white_spaces(line + 6);
+        } else if (strncmp(line, "kernel", 6) == 0) {
+            parsed[0] = discard_leading_white_spaces(line + 6);
+        } else if (strncmp(line, "mmap", 4) == 0) {
+            parsed[mmap_idx--] = discard_leading_white_spaces(line + 4);
+        }
+        line=strchr(line+1,'\n');
+    }
 
-    phi->cmdline = buf;
-    phi->cmdlen = cmdlen;
+    if (parsed_modules) {
+        *parsed_modules = parsed;
+    } else  {
+        free(parsed_modules);
+    }
 
+    if (mods) {
+        *mods = num_mod;
+    }
 
-    bp->cmdline_ptr = (uint32_t)(load_offset);
-    bp->cmdline_size = (uint32_t)cmdlen;
+    if (mmaps) {
+        *mmaps = num_mmap;
+    }
+
+    if (kernel) {
+        *kernel = has_kernel;
+    }
+
+    XBOOT_DEBUG("parsing modules found: %u kernel, %u modules, %u mmaps\n",
+                has_kernel, num_mod, num_mmap);
 
     return SYS_ERR_OK;
 }
 
-static errval_t bootstrap_notify(struct xeon_phi *phi)
+
+static errval_t load_mod_list_tftp(char *mod_list, void **modules, size_t *size)
 {
-    // set the bootimage size to tell the bootloader
-    xeon_phi_boot_os_size_rawwr(&boot_registers, phi->os_size);
+    errval_t err;
 
-    uint64_t memsize = get_adapter_memsize();
+    void *buf = calloc(1, TFTP_BUF_SIZE);
 
-    uint64_t reserved = (memsize * MEMORY_RESERVE_PERCENT / 100);
+    XBOOT_DEBUG("loading modules list %s over TFTP\n", mod_list);
 
-    // Keep in mind maximum uos reserve size is uint32_t, so we never overflow
-    reserved = MIN(reserved, UOS_RESERVE_SIZE_MAX);
-    reserved = MAX(reserved, UOS_RESERVE_SIZE_MIN);
+    err = tftp_client_read_file(mod_list, buf, TFTP_BUF_SIZE, size);
+    if (err_is_fail(err)) {
+        USER_PANIC("reading tftp file");
+    }
 
-    // Always align uos reserve size to a page
-    reserved = (reserved & ~(BASE_PAGE_SIZE - 1));
+    if (modules) {
+        *modules = buf;
+    }
 
-    xeon_phi_boot_res_size_rawwr(&boot_registers, (uint32_t) reserved);
+    return SYS_ERR_OK;
+}
 
-    // sending the bootstrap interrupt
-    xeon_phi_apic_icr_lo_t icr_lo = xeon_phi_apic_icr_lo_default;
-    icr_lo = xeon_phi_apic_icr_lo_vector_insert(icr_lo, xeon_phi_apic_vec_bsp);
-    icr_lo = xeon_phi_apic_icr_lo_boot_notify_insert(icr_lo, 0x1);
+static errval_t load_mod_list_vfs(char *mod_list, uint8_t use_nfs,
+                                  void **modules, size_t *size)
+{
+    errval_t err;
 
-    assert(icr_lo == (229 | (1 << 13)));
+    XBOOT_DEBUG("loading modules list %s %s\n", mod_list,
+                (use_nfs==1 ? "over NFS" : "from ramfs"));
 
-    xeon_phi_apic_icr_hi_wr(&apic_registers, xeon_phi_apic_bootstrap, phi->apicid);
+    /* load the menu lst file */
+    vfs_handle_t fh = file_open(mod_list, use_nfs);
+    if (fh == NULL) {
+        return SPAWN_ERR_LOAD;
+    }
 
-    xeon_phi_apic_icr_lo_wr(&apic_registers, xeon_phi_apic_bootstrap, icr_lo);
+    struct vfs_fileinfo info;
+    err = vfs_stat(fh, &info);
+    if (err_is_fail(err)) {
+        vfs_close(fh);
+        return err_push(err, SPAWN_ERR_LOAD);
+    }
+
+    assert(info.type == VFS_FILE);
+
+    char *menulst = calloc(info.size + 1, 1);
+    if (menulst == NULL) {
+        vfs_close(fh);
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    err = file_load(fh, menulst, info.size);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "file loading failed.\n");
+        vfs_close(fh);
+        free(menulst);
+        return err;
+    }
+
+    if (modules) {
+        *modules = menulst;
+    }
+
+    if (size) {
+        *size = info.size;
+    }
 
     return SYS_ERR_OK;
 }
@@ -358,12 +646,12 @@ static errval_t bootstrap_notify(struct xeon_phi *phi)
  * \brief boots the card with the given loader and multiboot image
  *
  * \param phi           pointer to the card information
- * \param xloader_img   pointer to the card bootloader image
- * \param multiboot_img pointer to the card multiboot image
+ * \param mod_uri       name of to the modules location uri
+ * \param mod_list      name of the modules list
  */
 errval_t xeon_phi_boot(struct xeon_phi *phi,
-                       char *xloader_img,
-                       char *multiboot_img)
+                       char *mod_uri,
+                       char *mod_list)
 {
     errval_t err;
     lvaddr_t offset;
@@ -375,20 +663,62 @@ errval_t xeon_phi_boot(struct xeon_phi *phi,
 
     phi->apicid = xeon_phi_boot_download_apicid_rdf(&boot_registers);
 
-    // load the coprocessor OS
-    err = load_bootloader(phi, xloader_img);
+    void *modules = NULL;
+    size_t modules_size = 0;
+    uint8_t use_nfs = 0, use_tftp = 0;
+    if (strncmp(mod_uri, "nfs://", 6) == 0) {
+        XBOOT_DEBUG("using nfs share: %s\n", mod_uri);
+        use_nfs = 1;
+        err = load_mod_list_vfs(mod_list, 1, &modules, &modules_size);
+    } else if (strncmp(mod_uri, "tftp://", 7) == 0) {
+        use_tftp = 1;
+        char *del = strchr(mod_uri+7, ':');\
+        uint16_t port = 69; // default tftp port
+        if (del != NULL) {
+            port = atoi(del + 1);
+            *del = 0;
+        }
+
+        XBOOT_DEBUG("using tftp server: %s @ port %u\n", mod_uri + 7, port);
+
+        err = tftp_client_connect(mod_uri + 7, port);
+        if (err_is_fail(err)) {
+            USER_PANIC_ERR(err, "Could not connect to the tftp service");
+        }
+        err = load_mod_list_tftp(mod_list, &modules, &modules_size);
+    } else  {
+        err = load_mod_list_vfs(mod_list, 0, &modules, &modules_size);
+    }
+
     if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "Could not load bootloader image");
+        USER_PANIC_ERR(err, "failed to load modules list");
     }
 
-    // round to next page
-    offset = ALIGN(phi->os_offset + phi->os_size);
+    char **modules_parsed;
+    uint32_t num_mods, num_mmaps;
+    uint8_t has_kernel;
+    err = parse_mod_list(modules, &num_mods, &num_mmaps, &has_kernel, &modules_parsed);
+    if (err_is_fail(err)) {
+        return err;
+    }
 
-    err = interphi_init(phi, NULL_CAP);
+    if (!has_kernel) {
+        return SPAWN_ERR_FIND_MODULE;
+    }
+
+    // load the coprocessor OS (boot loader)
+    if (use_tftp) {
+        err = download_bootloader_tftp(phi, modules_parsed[0]);
+    } else {
+        err = download_bootloader_vfs(phi, modules_parsed[0], use_nfs);
+    }
     if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "Could not initialize messaging");
+        USER_PANIC_ERR(err, "Could not load bootloader image");
     }
 
+    // round to next page
+    offset = ALIGN(phi->os_offset + phi->os_size);
+
     // load cmdline
     err = load_cmdline(phi, offset);
     if (err_is_fail(err)) {
@@ -398,10 +728,19 @@ errval_t xeon_phi_boot(struct xeon_phi *phi,
     // round to next page
     offset = ALIGN(offset+phi->cmdlen);
 
-    // load multiboot image
-    err = load_multiboot_image(phi, multiboot_img, offset);
+    if (use_tftp) {
+        err = download_modules_tftp(phi, offset, modules_parsed + 1, num_mods, num_mmaps);
+    } else {
+        err = download_modules_vfs(phi, offset, modules_parsed + 1, num_mods, num_mmaps, use_nfs);
+    }
     if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "Could not load multiboot image");
+         USER_PANIC_ERR(err, "Could not load multiboot image");
+    }
+
+    free(modules_parsed);
+
+    if (use_tftp) {
+        tftp_client_disconnect();
     }
 
     struct xeon_phi_boot_params *bp;
@@ -409,6 +748,11 @@ errval_t xeon_phi_boot(struct xeon_phi *phi,
     bp->xeon_phi_id = 0xFF00;
     bp->xeon_phi_id |= phi->id;
 
+    err = interphi_init(phi, NULL_CAP);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "Could not initialize messaging");
+    }
+
     xeon_phi_boot_download_status_wrf(&boot_registers, 0x0);
 
     phi->apicid = xeon_phi_boot_download_apicid_rdf(&boot_registers);
index 0119df1..124df14 100644 (file)
@@ -50,7 +50,7 @@ static errval_t mount_nfs_path(char *uri)
 {
     errval_t err;
 
-    if (uri == NULL) {
+    if (uri == NULL || strncmp(uri, "nfs://", 6)) {
         return SYS_ERR_OK;
     }
 
@@ -127,9 +127,8 @@ int main(int argc,
 {
     errval_t err;
 
-    char *xeon_phi_bootloader_path = XEON_PHI_BOOTLOADER;
-    char *xeon_phi_nfs_uri = XEON_PHI_NFS_PATH;
-    char *xeon_phi_multiboot_path = XEON_PHI_MULTIBOOT;
+    char *xeon_phi_mod_uri = XEON_PHI_NFS_PATH;
+    char *xeon_phi_mod_list = XEON_PHI_MOD_LIST;
 
     uint8_t xeon_phi_dma_enabled = 1;
 
@@ -171,13 +170,12 @@ int main(int argc,
     }
 
     for (uint8_t i = 1; i < argc - 1; ++i) {
-        if (strncmp(argv[i], "--nfs=", 6)==0) {
-            xeon_phi_nfs_uri = argv[i] + 6;
-            xphi.use_nfs = 1;
-        } else if (strncmp(argv[i], "--bootloader=", 13)==0) {
-            xeon_phi_bootloader_path = argv[i] + 14;
-        } else if (strncmp(argv[i], "--multiboot=", 12)==0) {
-            xeon_phi_multiboot_path = argv[i] + 12;
+        if (strncmp(argv[i], "--tftp=", 7)==0) {
+            xeon_phi_mod_uri = argv[i] + 7;
+        } else if (strncmp(argv[i], "--nfs=", 6)==0) {
+            xeon_phi_mod_uri = argv[i] + 6;
+        } else if (strncmp(argv[i], "--modlist=", 10)==0) {
+            xeon_phi_mod_list = argv[i] + 10;
         } else if (strncmp(argv[i], "--no-dma", 8)==0) {
             xeon_phi_dma_enabled = 0;
         } else if (strncmp(argv[i], "auto", 4)==0) {
@@ -187,8 +185,8 @@ int main(int argc,
         }
     }
 
-    XDEBUG("Xeon Phi Images: bootloader: {%s}, multiboot: {%s}, nfs: {%s}\n",
-           xeon_phi_bootloader_path, xeon_phi_multiboot_path, xeon_phi_nfs_uri);
+    XDEBUG("Xeon Phi Images: mod_list: {%s}, mod_uri: {%s}\n", xeon_phi_mod_list,
+           xeon_phi_mod_uri);
 
     /* set the client flag to false */
     xphi.is_client = XEON_PHI_IS_CLIENT;
@@ -201,7 +199,7 @@ int main(int argc,
     }
 
     // map the nfs path
-    err = mount_nfs_path(xeon_phi_nfs_uri);
+    err = mount_nfs_path(xeon_phi_mod_uri);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "could not map the NFS paths");
     }
@@ -230,7 +228,7 @@ int main(int argc,
         USER_PANIC_ERR(err, "could not register with the other drivers");
     }
 
-    err = xeon_phi_boot(&xphi, xeon_phi_bootloader_path, xeon_phi_multiboot_path);
+    err = xeon_phi_boot(&xphi, xeon_phi_mod_uri, xeon_phi_mod_list);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "could not boot the card\n");
     }
index 16e6024..53b2418 100644 (file)
@@ -21,8 +21,8 @@
 /// the name of the Xeon Phi bootloader image
 #define XEON_PHI_BOOTLOADER "/weever"
 
-/// the name of the Xeon Phi multiboot image containint the modules
-#define XEON_PHI_MULTIBOOT "/xeon_phi_multiboot"
+/// name of the file containing the modules to be loaded
+#define XEON_PHI_MOD_LIST "menu.lst.k1om"
 
 /// the name fo the nfs path to mount
 #define XEON_PHI_NFS_PATH NULL
@@ -118,7 +118,6 @@ struct xeon_phi
     uint32_t os_size;       ///< the size of the OS image
     char *cmdline;          ///< pointer to the bootloader cmdline
     uint32_t cmdlen;        ///< the length of the cmd line
-    uint8_t use_nfs;        ///< the bootmodules are on a NFS location
 
     uint8_t id;             ///< card id for identifying the card
     iref_t iref;