/** * \file * \brief init process for child spawning */ /* * Copyright (c) 2007, 2008, 2009, 2010, 2016, 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. */ #include #include #include #include #include #include #include #include #include #include #include "mem_alloc.h" #include #include #include #include struct bootinfo *bi; coreid_t my_core_id; struct platform_info platform_info; // only valid on app core static struct aos_urpc urpc_to_bsp; // only valid on app core static struct aos_urpc_server urpc_to_app_server; // only valid on bsp core struct aos_urpc urpc_to_app; struct waitset urpc_to_app_ws; static errval_t ram_alloc_remote_core(struct capref *ret, size_t size, size_t alignment) { errval_t err; err = do_aos_urpc( &urpc_to_bsp, RPC_MTYPE_GET_RAM_CAP, NULL_CAP, 0, size, alignment, ret, NULL, NULL, NULL ); if (err_is_fail(err)) return err_push(err, LIB_ERR_RAM_ALLOC); return SYS_ERR_OK; } static int bsp_main(int argc, char *argv[]) { errval_t err; // Grading grading_setup_bsp_init(argc, argv); // First argument contains the bootinfo location, if it's not set bi = (struct bootinfo*)strtol(argv[1], NULL, 10); assert(bi); err = initialize_ram_alloc(); if(err_is_fail(err)){ DEBUG_ERR(err, "initialize_ram_alloc"); } // TODO: initialize mem allocator, vspace management here err = cap_retype(cap_selfep, cap_dispatcher, 0, ObjType_EndPointLMP, 0, 1); if (err_is_fail(err)) return err; // Grading grading_test_early(); // TODO: Spawn system processes, boot second core etc. here // A URPC frame, to hold the cross-core communication channels that you // will implement in Section 7.16. struct capref urpc_frame; err = frame_alloc(&urpc_frame, MON_URPC_SIZE, NULL); if(err_is_fail(err)) return err_push(err, LIB_ERR_FRAME_ALLOC); struct frame_identity urpc_frame_id; err = frame_identify(urpc_frame, &urpc_frame_id); if(err_is_fail(err)) return err_push(err, LIB_ERR_CAP_IDENTIFY); // boot second core char *cpu_driver_name; switch (platform_info.platform) { case PI_PLATFORM_QEMU: cpu_driver_name = "cpu_a57_qemu"; break; case PI_PLATFORM_IMX8X: cpu_driver_name = "cpu_imx8x"; break; default: USER_PANIC("Platform not implemented"); } void *urpc_addr; err = paging_map_frame(get_current_paging_state(), &urpc_addr, MON_URPC_SIZE, urpc_frame); if (err_is_fail(err)) return err; memset(urpc_addr, 0, MON_URPC_SIZE); // memory barrier __asm volatile ( "dmb sy\n" ); cpu_idcache_wbinv_range((uintptr_t)urpc_addr, MON_URPC_SIZE); // TODO rueegges: can we get the mpid in a better way? err = coreboot(1, "boot_armv8_generic", cpu_driver_name, "init", urpc_frame_id); if (err_is_fail(err)) return err_push(err, MON_ERR_SPAWN_CORE); // err = coreboot(2, "boot_armv8_generic", cpu_driver_name, "init", urpc_frame_id); // if (err_is_fail(err)) return err_push(err, MON_ERR_SPAWN_CORE); // err = coreboot(3, "boot_armv8_generic", cpu_driver_name, "init", urpc_frame_id); // if (err_is_fail(err)) return err_push(err, MON_ERR_SPAWN_CORE); struct aos_urpc_frame *urpc = urpc_addr; struct aos_urpc_server *urpc_to_bsp_server = malloc(sizeof(struct aos_urpc_server)); urpc_to_bsp_server->g.shared_mem = &urpc->shared_mem_to_bsp; urpc_to_bsp_server->g.async_reply = NULL; urpc_to_bsp_server->meta = &urpc->meta_to_bsp; thread_create(urpc_server, urpc_to_bsp_server); urpc_to_app.shared_mem = &urpc->shared_mem_to_app; urpc_to_app.meta = &urpc->meta_to_app; waitset_init(&urpc_to_app_ws); thread_create(urpc_client_loop, &urpc_to_app_ws); // Grading grading_test_late(); debug_printf("Message handler loop\n"); // Hang around struct waitset *default_ws = get_default_waitset(); while (true) { err = event_dispatch(default_ws); if (err_is_fail(err)) { DEBUG_ERR(err, "in event_dispatch"); abort(); } } return EXIT_SUCCESS; } static errval_t deserialize_bootinfo(struct bootinfo_serialized * serialized, struct bootinfo ** ret) { errval_t err; assert(serialized != NULL); size_t bootinfo_size = sizeof(struct bootinfo) + serialized->regions_length * sizeof(struct mem_region); // struct capref ret_frame; // err = frame_alloc(&ret_frame, bootinfo_size, NULL); // if (err_is_fail(err)) return err_push(err, LIB_ERR_FRAME_ALLOC); // err = paging_map_frame(get_current_paging_state(), (void **) ret, bootinfo_size, ret_frame); // if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_MAP); *ret = malloc(bootinfo_size); if(*ret == NULL) return LIB_ERR_MALLOC_FAIL; (*ret)->host_msg = serialized->host_msg; (*ret)->host_msg_bits = serialized->host_msg_bits; (*ret)->mem_spawn_core = serialized->mem_spawn_core; (*ret)->regions_length = serialized->regions_length; //forge the slot 0 cap struct capref slot_0_forge_destination = { .cnode = cnode_module, .slot = 0, }; err = devframe_forge(slot_0_forge_destination, serialized->slot_0_frame_base, serialized->slot_0_frame_bytes, my_core_id); if (err_is_fail(err)) return err; for (int i = 0; i < serialized->regions_length; ++i) { (*ret)->regions[i].mr_base = serialized->regions[i].mr_base; (*ret)->regions[i].mr_bytes = serialized->regions[i].mr_bytes; (*ret)->regions[i].mr_type = serialized->regions[i].mr_type; (*ret)->regions[i].mr_consumed = serialized->regions[i].mr_consumed; (*ret)->regions[i].mrmod_size = serialized->regions[i].mrmod_size; (*ret)->regions[i].mrmod_data = serialized->regions[i].mrmod_data; (*ret)->regions[i].mrmod_slot = serialized->regions[i].mrmod_slot; if (serialized->regions[i].mr_type != RegionType_Module) { continue; } //forge cap struct capref forge_destination = { .cnode = cnode_module, .slot = serialized->regions[i].mrmod_slot, }; err = devframe_forge(forge_destination, serialized->regions[i].mrmod_frame_base, serialized->regions[i].mrmod_frame_bytes, my_core_id); if (err_is_fail(err)) return err; } return SYS_ERR_OK; } static int app_main(int argc, char *argv[]) { errval_t err; debug_printf("[app_main]\n"); // Implement me in Milestone 5 // Remember to call // - grading_setup_app_init(..); // - grading_test_early(); // - grading_test_late(); // Grading grading_setup_app_init(bi); // TODO: initialize mem allocator, vspace management here err = cap_retype(cap_selfep, cap_dispatcher, 0, ObjType_EndPointLMP, 0, 1); if (err_is_fail(err)) return err; struct aos_urpc_frame *urpc = (void*)MON_URPC_VBASE; urpc_to_bsp.shared_mem = &urpc->shared_mem_to_bsp; urpc_to_bsp.meta = &urpc->meta_to_bsp; urpc_to_app_server.g.shared_mem = &urpc->shared_mem_to_app; urpc_to_app_server.g.async_reply = NULL; urpc_to_app_server.meta = &urpc->meta_to_app; ram_alloc_set(ram_alloc_remote_core); thread_create(urpc_server, &urpc_to_app_server); // Grading grading_test_early(); // TODO: Spawn system processes etc. here struct bootinfo_serialized * bi_ser; err = aos_urpc_get_bootinfo(&urpc_to_bsp, &bi_ser); if (err_is_fail(err)) return err; err = deserialize_bootinfo(bi_ser, &bi); free(bi_ser); if (err_is_fail(err)) return err; debug_printf("[app_main]: received bootinfo with %d regions\n", bi->regions_length); // Grading grading_test_late(); debug_printf("Message handler loop\n"); // Hang around struct waitset *default_ws = get_default_waitset(); while (true) { err = event_dispatch(default_ws); if (err_is_fail(err)) { DEBUG_ERR(err, "in event_dispatch"); abort(); } } return EXIT_SUCCESS; } int main(int argc, char *argv[]) { errval_t err; /* obtain the core information from the kernel*/ err = invoke_kernel_get_core_id(cap_kernel, &my_core_id); if (err_is_fail(err)) { USER_PANIC_ERR(err, "failed to obtain the core id from the kernel\n"); } /* Set the core id in the disp_priv struct */ disp_set_core_id(my_core_id); /* obtain the platform information */ err = invoke_kernel_get_platform_info(cap_kernel, &platform_info); if (err_is_fail(err)) { USER_PANIC_ERR(err, "failed to obtain the platform info from the kernel\n"); } char *platform; switch (platform_info.platform) { case PI_PLATFORM_QEMU: platform = "QEMU"; break; case PI_PLATFORM_IMX8X: platform = "IMX8X"; break; default: platform = "UNKNOWN"; } debug_printf("init domain starting on core %" PRIuCOREID " (%s), invoked as:", my_core_id, platform); for (int i = 0; i < argc; i++) { printf(" %s", argv[i]); } printf("\n"); fflush(stdout); if(my_core_id == 0) return bsp_main(argc, argv); else return app_main(argc, argv); }