Пример #1
0
struct dcb *spawn_bsp_init(const char *name, alloc_phys_func alloc_phys)
{
    printf("spawn_bsp_init\n");

    /* Only the first core can run this code */
    assert(hal_cpu_is_bsp());

    /* Allocate bootinfo */
    lpaddr_t bootinfo_phys = alloc_phys(BOOTINFO_SIZE);
    memset((void *)local_phys_to_mem(bootinfo_phys), 0, BOOTINFO_SIZE);

    /* Construct cmdline args */
    char bootinfochar[16];
    snprintf(bootinfochar, sizeof(bootinfochar), "%u", INIT_BOOTINFO_VBASE);
    const char *argv[] = { "init", bootinfochar };
    int argc = 2;

    struct dcb *init_dcb = spawn_init_common(name, argc, argv, bootinfo_phys,
            alloc_phys);

    // Map bootinfo
    spawn_init_map(init_l2, INIT_VBASE, INIT_BOOTINFO_VBASE,
                   bootinfo_phys, BOOTINFO_SIZE, INIT_PERM_RW);

    struct startup_l2_info l2_info = { init_l2, INIT_VBASE };

    genvaddr_t init_ep, got_base;
    load_init_image(&l2_info, BSP_INIT_MODULE_NAME, &init_ep, &got_base);

    struct dispatcher_shared_arm *disp_arm
        = get_dispatcher_shared_arm(init_dcb->disp);
    disp_arm->enabled_save_area.named.r10  = got_base;
    disp_arm->got_base = got_base;

    disp_arm->disabled_save_area.named.pc   = init_ep;
#ifndef __ARM_ARCH_7M__ //the armv7-m profile does not have such a mode field
    disp_arm->disabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK;
#endif
    disp_arm->disabled_save_area.named.r10  = got_base;

    /* Create caps for init to use */
    create_module_caps(&spawn_state);
    lpaddr_t init_alloc_end = alloc_phys(0); // XXX
    create_phys_caps(init_alloc_end);

    /* Fill bootinfo struct */
    bootinfo->mem_spawn_core = KERNEL_IMAGE_SIZE; // Size of kernel

    /*
    // Map dispatcher
    spawn_init_map(init_l2, INIT_VBASE, INIT_DISPATCHER_VBASE,
                   mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE,
                   INIT_PERM_RW);
    disp_arm->disabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
	*/
    return init_dcb;
}
Пример #2
0
void arm_kernel_startup(phys_mmap_t* mmap,
                        lpaddr_t     initrd_base,
                        size_t       initrd_bytes)
{
    g_phys_mmap = mmap;

    STARTUP_PROGRESS();

#ifdef __XSCALE__
    //Hardcoded because bootloader alter image if we pass the correct location
    //Size of image is obtained by header file which is generated during compilation
    initrd_base = 0x20000000;
    initrd_bytes = romfs_cpio_archive_size;
#endif

    const uint8_t* initrd_cpio_base = (uint8_t*)local_phys_to_mem(initrd_base);

    if (!cpio_archive_valid(initrd_cpio_base, initrd_bytes))
    {
                panic("Invalid initrd filesystem\n");
    }

    /* allocate initial KCB */
    kcb_current = (struct kcb *) local_phys_to_mem(alloc_phys(sizeof(*kcb_current)));
    memset(kcb_current, 0, sizeof(*kcb_current));
    assert(kcb_current);

    spawn_init(BSP_INIT_MODULE_NAME, 0, initrd_cpio_base, initrd_bytes);
}
Пример #3
0
static errval_t
startup_alloc_init(
    void*      state,
    genvaddr_t gvbase,
    size_t     bytes,
    uint32_t   flags,
    void**     ret
    )
{
    const struct startup_l2_info* s2i = (const struct startup_l2_info*)state;

    lvaddr_t sv = round_down((lvaddr_t)gvbase, BASE_PAGE_SIZE);
    size_t   off = (lvaddr_t)gvbase - sv;
    lvaddr_t lv = round_up((lvaddr_t)gvbase + bytes, BASE_PAGE_SIZE);
    lpaddr_t pa;

    STARTUP_PROGRESS();
    if (lv > sv && ((pa = alloc_phys(lv - sv)) != 0))
    {
        spawn_init_map(s2i->l2_table, s2i->l2_base, sv,
                       pa, lv - sv, elf_to_l2_flags(flags));
        *ret = (void*)(local_phys_to_mem(pa) + off);
    }
    else
    {
        *ret = 0;
    }
    return SYS_ERR_OK;
}
Пример #4
0
spawn_init(const char*      name,
           int32_t          kernel_id,
           const uint8_t*   initrd_base,
           size_t           initrd_bytes)
{
    assert(0 == kernel_id);

    // Create page table for init

    init_l1 =  (uintptr_t*)alloc_mem_aligned(INIT_L1_BYTES, ARM_L1_ALIGN);
    memset(init_l1, 0, INIT_L1_BYTES);

    init_l2 = (uintptr_t*)alloc_mem_aligned(INIT_L2_BYTES, ARM_L2_ALIGN);
    memset(init_l2, 0, INIT_L2_BYTES);

    STARTUP_PROGRESS();

    /* Allocate bootinfo */
    lpaddr_t bootinfo_phys = alloc_phys(BOOTINFO_SIZE);
    memset((void *)local_phys_to_mem(bootinfo_phys), 0, BOOTINFO_SIZE);

    STARTUP_PROGRESS();

    /* Construct cmdline args */
    char bootinfochar[16];
    snprintf(bootinfochar, sizeof(bootinfochar), "%u", INIT_BOOTINFO_VBASE);
    const char *argv[] = { "init", bootinfochar };

    lvaddr_t paramaddr;
    struct dcb *init_dcb = spawn_module(&spawn_state, name,
                                        ARRAY_LENGTH(argv), argv,
                                        bootinfo_phys, INIT_ARGS_VBASE,
                                        alloc_phys, &paramaddr);

    STARTUP_PROGRESS();

    /*
     * Create a capability that allows user-level applications to
     * access device memory. This capability will be passed to Kaluga,
     * split up into smaller pieces and distributed to among device
     * drivers.
     *
     * For armv5, this is currently a dummy capability. We do not
     * have support for user-level device drivers in gem5 yet, so we
     * do not allocate any memory as device memory. Some cap_copy
     * operations in the bootup code fail if this capability is not
     * present.
     */
    struct cte *iocap = caps_locate_slot(CNODE(spawn_state.taskcn), TASKCN_SLOT_IO);
    errval_t  err = caps_create_new(ObjType_IO, 0, 0, 0, my_core_id, iocap);
    assert(err_is_ok(err));

    struct dispatcher_shared_generic *disp
        = get_dispatcher_shared_generic(init_dcb->disp);
    struct dispatcher_shared_arm *disp_arm
        = get_dispatcher_shared_arm(init_dcb->disp);
    assert(NULL != disp);

    STARTUP_PROGRESS();

    /* Initialize dispatcher */
    disp->udisp = INIT_DISPATCHER_VBASE;

    STARTUP_PROGRESS();
    init_dcb->vspace = mem_to_local_phys((lvaddr_t)init_l1);

    STARTUP_PROGRESS();

    /* Page table setup */

    /* Map pagetables into page CN */
    int pagecn_pagemap = 0;

    /*
     * ARM has:
     *
     * L1 has 4096 entries (16KB).
     * L2 Coarse has 256 entries (256 * 4B = 1KB).
     *
     * CPU driver currently fakes having 1024 entries in L1 and
     * L2 with 1024 entries by treating a page as 4 consecutive
     * L2 tables and mapping this as a unit in L1.
     */
    caps_create_new(
        ObjType_VNode_ARM_l1,
        mem_to_local_phys((lvaddr_t)init_l1),
            vnode_objbits(ObjType_VNode_ARM_l1), 0,
            my_core_id,
            caps_locate_slot(CNODE(spawn_state.pagecn), pagecn_pagemap++)
        );

    STARTUP_PROGRESS();

    // Map L2 into successive slots in pagecn
    size_t i;
    for (i = 0; i < INIT_L2_BYTES / BASE_PAGE_SIZE; i++) {
        size_t objbits_vnode = vnode_objbits(ObjType_VNode_ARM_l2);
        assert(objbits_vnode == BASE_PAGE_BITS);
        caps_create_new(
            ObjType_VNode_ARM_l2,
            mem_to_local_phys((lvaddr_t)init_l2) + (i << objbits_vnode),
            objbits_vnode, 0,
            my_core_id,
            caps_locate_slot(CNODE(spawn_state.pagecn), pagecn_pagemap++)
            );
    }

    /*
     * Initialize init page tables - this just wires the L1
     * entries through to the corresponding L2 entries.
     */
    STATIC_ASSERT(0 == (INIT_VBASE % ARM_L1_SECTION_BYTES), "");
    for (lvaddr_t vaddr = INIT_VBASE; vaddr < INIT_SPACE_LIMIT; vaddr += ARM_L1_SECTION_BYTES)
    {
        uintptr_t section = (vaddr - INIT_VBASE) / ARM_L1_SECTION_BYTES;
        uintptr_t l2_off = section * ARM_L2_TABLE_BYTES;
        lpaddr_t paddr = mem_to_local_phys((lvaddr_t)init_l2) + l2_off;
        paging_map_user_pages_l1((lvaddr_t)init_l1, vaddr, paddr);
    }

    paging_make_good((lvaddr_t)init_l1, INIT_L1_BYTES);

    STARTUP_PROGRESS();

    printf("XXX: Debug print to make Bram's code work\n");

    paging_context_switch(mem_to_local_phys((lvaddr_t)init_l1));

    STARTUP_PROGRESS();

    // Map cmdline arguments in VSpace at ARGS_BASE
    STATIC_ASSERT(0 == (ARGS_SIZE % BASE_PAGE_SIZE), "");

    STARTUP_PROGRESS();

    spawn_init_map(init_l2, INIT_VBASE, INIT_ARGS_VBASE,
                   spawn_state.args_page, ARGS_SIZE, INIT_PERM_RW);

    STARTUP_PROGRESS();

    // Map bootinfo
    spawn_init_map(init_l2, INIT_VBASE, INIT_BOOTINFO_VBASE,
                   bootinfo_phys, BOOTINFO_SIZE, INIT_PERM_RW);

    struct startup_l2_info l2_info = { init_l2, INIT_VBASE };

    genvaddr_t init_ep, got_base;
    load_init_image(&l2_info, initrd_base, initrd_bytes, &init_ep, &got_base);

    // Set startup arguments (argc, argv)
    disp_arm->enabled_save_area.named.r0   = paramaddr;
    disp_arm->enabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK;
    disp_arm->enabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
    disp_arm->enabled_save_area.named.r10  = got_base;

    disp_arm->got_base = got_base;

    struct bootinfo* bootinfo = (struct bootinfo*)INIT_BOOTINFO_VBASE;
    bootinfo->regions_length = 0;

    STARTUP_PROGRESS();

    create_modules_from_initrd(bootinfo, initrd_base, initrd_bytes);
    debug(SUBSYS_STARTUP, "used %"PRIuCSLOT" slots in modulecn\n", spawn_state.modulecn_slot);

    STARTUP_PROGRESS();
    create_phys_caps(&spawn_state.physaddrcn->cap, bootinfo);

    STARTUP_PROGRESS();

    bootinfo->mem_spawn_core  = ~0;     // Size of kernel if bringing up others

    // Map dispatcher
    spawn_init_map(init_l2, INIT_VBASE, INIT_DISPATCHER_VBASE,
                   mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE,
                   INIT_PERM_RW);

    STARTUP_PROGRESS();

    // NB libbarrelfish initialization sets up the stack.
    disp_arm->disabled_save_area.named.pc   = init_ep;
    disp_arm->disabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK;
    disp_arm->disabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
    disp_arm->disabled_save_area.named.r10  = got_base;

#ifdef __XSCALE__
    cp15_disable_cache();
#endif

    printf("Kernel ready.\n");

    pit_start();

    // On to userland...
    STARTUP_PROGRESS();
    dispatch(init_dcb);

    panic("Not reached.");
}
Пример #5
0
static void
create_modules_from_initrd(struct bootinfo* bi,
                           const uint8_t*   initrd_base,
                           size_t           initrd_bytes)
{
    errval_t err;
    lvaddr_t mmstrings_base = 0;
    lvaddr_t mmstrings      = 0;

    // CPIO archive is crafted such that first file is
    // command-line strings for "modules" - ie menu.lst. The
    // subsequent file follow in the order they appear in
    // menu.lst.arm.
    const uint8_t* data;
    size_t bytes;

    if (cpio_get_file_by_name(initrd_base, initrd_bytes,
                              "menu.lst.modules",
                              &data, &bytes))
    {
        assert(bytes < BASE_PAGE_SIZE);

        mmstrings_base = alloc_mem(BASE_PAGE_SIZE);
        mmstrings      = mmstrings_base;

        STARTUP_PROGRESS();

        // Create cap for strings area in first slot of modulecn
        err = caps_create_new(
                  ObjType_Frame,
                  mem_to_local_phys(mmstrings_base),
                  BASE_PAGE_BITS, BASE_PAGE_BITS,
                  my_core_id,
                  caps_locate_slot(
                      CNODE(spawn_state.modulecn),
                      spawn_state.modulecn_slot++)
                  );
        assert(err_is_ok(err));

        STARTUP_PROGRESS();

        // Copy strings from file into allocated page
        memcpy((void*)mmstrings_base, data, bytes);
        ((char*)mmstrings_base)[bytes] = '\0';

        STARTUP_PROGRESS();

        // Skip first line (corresponds to bootscript in archive)
        strtok((char*)mmstrings_base, "\r\n");

        STARTUP_PROGRESS();

        assert(bi->regions_length == 0);
        int ord = 1;
        const char* name;
        while ((mmstrings = (lvaddr_t)strtok(NULL, "\r\n")) != 0)
        {
            if (!cpio_get_file_by_ordinal(initrd_base, initrd_bytes, ord,
                                          &name, &data, &bytes))
            {
                panic("Failed to find file\n");
            }
            ord++;

            debug(SUBSYS_STARTUP,
                  "Creating caps for \"%s\" (Command-line \"%s\")\n",
                   name, (char*)mmstrings);

            // Copy file from archive into RAM.
            // TODO: Give up archive space.
            size_t   pa_bytes = round_up(bytes, BASE_PAGE_SIZE);
            lpaddr_t pa       = alloc_phys(pa_bytes);
            memcpy((void*)local_phys_to_mem(pa), data, bytes);

            struct mem_region* region = &bi->regions[bi->regions_length++];
            region->mr_type    = RegionType_Module;
            region->mrmod_slot = spawn_state.modulecn_slot;
            region->mrmod_size = pa_bytes;
            region->mrmod_data = mmstrings - mmstrings_base;

            assert((pa & BASE_PAGE_MASK) == 0);
            assert((pa_bytes & BASE_PAGE_MASK) == 0);

            while (pa_bytes != 0)
            {
                assert(spawn_state.modulecn_slot
                       < (1UL << spawn_state.modulecn->cap.u.cnode.bits));
                // create as DevFrame cap to avoid zeroing memory contents
                err = caps_create_new(
                          ObjType_DevFrame, pa, BASE_PAGE_BITS,
                          BASE_PAGE_BITS,
                          my_core_id,
                          caps_locate_slot(
                              CNODE(spawn_state.modulecn),
                              spawn_state.modulecn_slot++)
                          );
                assert(err_is_ok(err));
                pa       += BASE_PAGE_SIZE;
                pa_bytes -= BASE_PAGE_SIZE;
            }
        }
    }
    else
    {
        panic("No command-line file.\n");
    }
}
Пример #6
0
struct dcb *spawn_bsp_init(const char *name, alloc_phys_func alloc_phys)
{
    errval_t err;

    /* Only the first core can run this code */
    assert(apic_is_bsp());
    
    /* Allocate bootinfo */
    lpaddr_t bootinfo_phys = alloc_phys(BOOTINFO_SIZE);
    memset((void *)local_phys_to_mem(bootinfo_phys), 0, BOOTINFO_SIZE);

    /* Construct cmdline args */
    char bootinfochar[16];
    snprintf(bootinfochar, sizeof(bootinfochar), "%"PRIuLPADDR, BOOTINFO_BASE);

    const char *argv[6] = { "init", bootinfochar };
    int argc = 2;

#ifdef __scc__
    if(glbl_core_data->urpc_frame_base != 0) {
        char coreidchar[10];
        snprintf(coreidchar, sizeof(coreidchar), "%d",
                 glbl_core_data->src_core_id);
        argv[argc++] = coreidchar;

        char chan_id_char[30];
        snprintf(chan_id_char, sizeof(chan_id_char), "chanid=%"PRIu32,
                 glbl_core_data->chan_id);
        argv[argc++] = chan_id_char;

        char urpc_frame_base_char[30];
        snprintf(urpc_frame_base_char, sizeof(urpc_frame_base_char),
                 "frame=%" PRIuGENPADDR, glbl_core_data->urpc_frame_base);
        argv[argc++] = urpc_frame_base_char;
    }
#endif

    struct dcb *init_dcb = spawn_init_common(&spawn_state, name, argc, argv,
                                             bootinfo_phys, alloc_phys);

    /* Map bootinfo R/W into VSpace at vaddr 0x200000 (BOOTINFO_BASE) */
#ifdef CONFIG_PAE
    paging_x86_32_map_pdpte(&init_pdpte[0], mem_to_local_phys((lvaddr_t)init_pdir));
    paging_x86_32_map_table(&init_pdir[1], mem_to_local_phys((lvaddr_t)init_ptable));
    for (int i = 0; i < BOOTINFO_SIZE / BASE_PAGE_SIZE; i++) {
        paging_x86_32_map(&init_ptable[i], bootinfo_phys + i * BASE_PAGE_SIZE,
                   INIT_PAGE_BITMAP | paging_elf_to_page_flags(PF_R|PF_W));
    }
#else
    paging_x86_32_map_table(&init_pdir[0], mem_to_local_phys((lvaddr_t)init_ptable));
    for (int i = 0; i < BOOTINFO_SIZE / BASE_PAGE_SIZE; i++) {
        paging_x86_32_map(&init_ptable[i + 512], bootinfo_phys + i * BASE_PAGE_SIZE,
                   INIT_PAGE_BITMAP | paging_elf_to_page_flags(PF_R|PF_W));
    }
#endif

    /* Load init ELF32 binary */
    struct multiboot_modinfo *module = multiboot_find_module(name);
    if (module == NULL) {
        panic("Could not find init module!");
    }
    genvaddr_t init_ep;
    err = elf_load(EM_386, startup_alloc_init, &spawn_state,
                   local_phys_to_mem(module->mod_start),
                   MULTIBOOT_MODULE_SIZE(*module), &init_ep);
    if (err_is_fail(err)) {
        //err_print_calltrace(err);
        panic("ELF load of init module failed!");
    }

    struct dispatcher_shared_x86_32 *init_disp_x86_32 =
        get_dispatcher_shared_x86_32(init_dcb->disp);
    init_disp_x86_32->disabled_save_area.eip = init_ep;

    /* Create caps for init to use */
    create_module_caps(&spawn_state);
    lpaddr_t init_alloc_end = alloc_phys(0); // XXX
    create_phys_caps(init_alloc_end);

    /* Fill bootinfo struct */
    bootinfo->mem_spawn_core = NEEDED_KERNEL_SPACE; // Size of kernel

    /* for (int i = 0; i < bootinfo->regions_length; i++) { */
    /*     printf("%d region %d: 0x%09" PRIxPTR " - 0x%09lx (%lu MB, %u bits)\n", */
    /*            bootinfo->regions[i].mr_type, i, bootinfo->regions[i].mr_base, */
    /*            bootinfo->regions[i].mr_base + (1UL<<bootinfo->regions[i].mr_bits), */
    /*            bootinfo->regions[i].mr_bits >= 20 */
    /*            ? 1UL << (bootinfo->regions[i].mr_bits - 20) : 0, */
    /*            bootinfo->regions[i].mr_bits); */
    /* } */

#if 0
    // If app core, map (static) URPC channel
    if(kernel_scckernel != 0) {
        printf("SCC app kernel, frame at: 0x%x\n", kernel_scckernel);
#define TASKCN_SLOT_MON_URPC    (TASKCN_SLOTS_USER+6)   ///< Frame cap for urpc comm.

        err = caps_create_new(ObjType_Frame, kernel_scckernel, 13, 13,
                              caps_locate_slot(CNODE(taskcn), TASKCN_SLOT_MON_URPC));
        assert(err_is_ok(err));
    }
#endif

    return init_dcb;
}