void pok_loader_load_partition (const uint8_t part_id, uint32_t offset, uint32_t *entry) { void* elf_entry = POK_NULL; extern char __archive2_begin; uint32_t size; uint16_t t; size = 0; t = 0; while (t < part_id) { size += part_sizes[t]; t++; } if (pok_partitions[part_id].size < part_sizes[part_id]) { #ifdef POK_NEEDS_ERROR_HANDLING pok_partition_error (part_id, POK_ERROR_KIND_PARTITION_CONFIGURATION); #else #ifdef POK_NEEDS_DEBUG /* We consider that even if errors are not raised, we must print an error * for such error * So, when we are using the debug mode, we print a fatal error. */ #include <core/debug.h> #include <stdio.h> printf("Declared size for partition %d : %d\n", part_id, pok_partitions[part_id].size); printf("Real size for partition %d : %d\n", part_id, part_sizes[part_id]); pok_fatal ("Partition size is not correct\n"); #endif #endif } pok_loader_elf_load ((&__archive2_begin) + size , offset, &elf_entry); *entry = (uint32_t)elf_entry; }
/** * \brief Initialize all partitions. * * It initializes everything, load the program, set thread * and lockobjects bounds. */ pok_ret_t pok_partition_init () { uint8_t i; uint32_t threads_index = 0; const uint32_t partition_size[POK_CONFIG_NB_PARTITIONS] = POK_CONFIG_PARTITIONS_SIZE; #if defined (POK_CONFIG_PARTITIONS_LOADADDR) && defined (POK_SKIP_LOADER) const uint32_t program_loadaddr[POK_CONFIG_NB_PARTITIONS] = POK_CONFIG_PARTITIONS_LOADADDR; #endif #ifdef POK_NEEDS_LOCKOBJECTS uint8_t lockobj_index = 0; #endif for (i = 0 ; i < POK_CONFIG_NB_PARTITIONS ; i++) { uint32_t size = partition_size[i]; uint32_t base_addr = (uint32_t)pok_bsp_mem_alloc(partition_size[i]); uint32_t program_entry; uint32_t base_vaddr = pok_space_base_vaddr(base_addr); #if defined (POK_CONFIG_PARTITIONS_LOADADDR) && defined (POK_SKIP_LOADER) // One may want to check that consistent addresses were specified printf ("Partition base addr phys=|%x| (user-defined |%x|)",base_addr, program_loadaddr[i]); #endif pok_partitions[i].base_addr = base_addr; pok_partitions[i].size = size; pok_partitions[i].sched = POK_SCHED_RR; pok_partitions[i].partition_id = i; //#ifdef POK_NEEDS_DEBUG //#include <libc.h> printf ("[XCOV] Partition %d loaded at addr virt=|%x|, phys=|%x|\n", i, base_vaddr, base_addr); //#endif pok_partition_setup_scheduler (i); pok_create_space (i, base_addr, size); pok_partitions[i].base_vaddr = base_vaddr; /* Set the memory space and so on */ pok_partitions[i].thread_index_low = threads_index; pok_partitions[i].nthreads = ((uint32_t[]) POK_CONFIG_PARTITIONS_NTHREADS) [i]; #ifdef POK_NEEDS_ERROR_HANDLING if (pok_partitions[i].nthreads <= 1) { pok_partition_error (i, POK_ERROR_KIND_PARTITION_CONFIGURATION); } #endif #ifdef POK_CONFIG_PARTITIONS_SCHEDULER pok_partitions[i].sched = ((pok_sched_t[]) POK_CONFIG_PARTITIONS_SCHEDULER) [i]; #endif pok_partitions[i].thread_index_high = pok_partitions[i].thread_index_low + ((uint32_t[]) POK_CONFIG_PARTITIONS_NTHREADS) [i]; pok_partitions[i].activation = 0; #ifdef POK_CONFIG_PARTITIONS_PERIOD pok_partitions[i].period = ((uint32_t[]) POK_CONFIG_PARTITIONS_PERIOD[i]); #else pok_partitions[i].period = POK_CONFIG_SCHEDULING_MAJOR_FRAME; #endif pok_partitions[i].thread_index = 0; pok_partitions[i].thread_main = 0; pok_partitions[i].current_thread = IDLE_THREAD; pok_partitions[i].prev_current_thread = IDLE_THREAD; threads_index = threads_index + pok_partitions[i].nthreads; /* Initialize the threading stuff */ pok_partitions[i].mode = POK_PARTITION_MODE_INIT_WARM; #ifdef POK_NEEDS_LOCKOBJECTS pok_partitions[i].lockobj_index_low = lockobj_index; pok_partitions[i].lockobj_index_high = lockobj_index + ((uint8_t[]) POK_CONFIG_PARTITIONS_NLOCKOBJECTS[i]); pok_partitions[i].nlockobjs = ((uint8_t[]) POK_CONFIG_PARTITIONS_NLOCKOBJECTS[i]); lockobj_index = lockobj_index + pok_partitions[i].nlockobjs; #endif #ifdef POK_NEEDS_ERROR_HANDLING pok_partitions[i].thread_error = 0; pok_partitions[i].error_status.failed_thread = 0; pok_partitions[i].error_status.failed_addr = 0; pok_partitions[i].error_status.error_kind = POK_ERROR_KIND_INVALID; pok_partitions[i].error_status.msg_size = 0; #endif #ifdef POK_NEEDS_DEBUG printf("loading partition\n"); #endif /** This invokation worked just because the base_vaddr was always 0 */ //pok_loader_load_partition (i, base_addr - base_vaddr, &program_entry); pok_loader_load_partition (i, base_addr, &program_entry); #ifdef POK_NEEDS_DEBUG printf("\t end loading partition\n"); #endif /* * Load the partition in its address space */ pok_partitions[i].thread_main_entry = program_entry; #ifdef POK_NEEDS_SCHED_O1_SPLIT /* initialize the successors bitmask with all zeros; we set to 1 the bits * corresponding to successor threads when the partition changes its mode to NORMAL. */ pok_partitions[i].successors = 0; /* initialize the executed_predecessors with all 1s; this because a thread that is * not a successor has its bit set to 1 in this bitmask (i.e. it can always execute). * We set to 0 the bits corresponding to successor threads when the partition change * its mode to NORMAL. */ pok_partitions[i].executed_predecessors = 1; /* initialize head and tail indexes of sporadic threads FIFO queue */ pok_partitions[i].head_index = 0; pok_partitions[i].tail_index = -1; /* initialize the FIFO queue; the queue is initialized with all bitmasks corresponding * to the idle thread */ int sporadic_index = 0; for (;sporadic_index<POK_CONFIG_NB_SPORADIC_THREADS;sporadic_index++) { pok_partitions[i].sporadic_ready_queue[sporadic_index] = 1 << (IDLE_THREAD - pok_partitions[i].thread_index_low); } #endif /* end ifdef POK_NEEDS_SCHED_O1_SPLIT */ } // end for for (i = 0 ; i < POK_CONFIG_NB_PARTITIONS ; i++) { pok_partition_setup_main_thread (i); } return POK_ERRNO_OK; }
/** * \brief Initialize all partitions. * * It initializes everything, load the program, set thread * and lockobjects bounds. */ pok_ret_t pok_partition_init () { uint8_t i; uint32_t threads_index = 0; const uint32_t partition_size[POK_CONFIG_NB_PARTITIONS] = POK_CONFIG_PARTITIONS_SIZE; #ifdef POK_CONFIG_PARTITIONS_LOADADDR const uint32_t program_loadaddr[POK_CONFIG_NB_PARTITIONS] = POK_CONFIG_PROGRAM_LOADADDR; #endif #ifdef POK_NEEDS_LOCKOBJECTS uint8_t lockobj_index = 0; #endif for (i = 0 ; i < POK_CONFIG_NB_PARTITIONS ; i++) { uint32_t size = partition_size[i]; #ifndef POK_CONFIG_PARTITIONS_LOADADDR uint32_t base_addr = (uint32_t)pok_bsp_mem_alloc(partition_size[i]); #else uint32_t base_addr = program_loadaddr[i]; #endif uint32_t program_entry; uint32_t base_vaddr = pok_space_base_vaddr(base_addr); pok_partitions[i].base_addr = base_addr; pok_partitions[i].size = size; pok_partitions[i].sched = POK_SCHED_RR; #ifdef POK_NEEDS_COVERAGE_INFOS #include <libc.h> printf ("[XCOV] Partition %d loaded at addr virt=|%x|, phys=|%x|\n", i, base_vaddr, base_addr); #endif pok_partition_setup_scheduler (i); pok_create_space (i, base_addr, size); pok_partitions[i].base_vaddr = base_vaddr; /* Set the memory space and so on */ pok_partitions[i].thread_index_low = threads_index; pok_partitions[i].nthreads = ((uint32_t[]) POK_CONFIG_PARTITIONS_NTHREADS) [i]; #ifdef POK_NEEDS_ERROR_HANDLING if (pok_partitions[i].nthreads <= 1) { pok_partition_error (i, POK_ERROR_KIND_PARTITION_CONFIGURATION); } #endif #ifdef POK_CONFIG_PARTITIONS_SCHEDULER pok_partitions[i].sched = ((pok_sched_t[]) POK_CONFIG_PARTITIONS_SCHEDULER) [i]; #endif pok_partitions[i].thread_index_high = pok_partitions[i].thread_index_low + ((uint32_t[]) POK_CONFIG_PARTITIONS_NTHREADS) [i]; pok_partitions[i].activation = 0; pok_partitions[i].period = 0; pok_partitions[i].thread_index = 0; pok_partitions[i].thread_main = 0; pok_partitions[i].current_thread = IDLE_THREAD; pok_partitions[i].prev_thread = IDLE_THREAD; // breaks the rule of prev_thread not being idle, but it's just for init #ifdef POK_NEEDS_SCHED_HFPPS pok_partitions[i].payback = 0; #endif /* POK_NEEDS_SCHED_HFPPS */ threads_index = threads_index + pok_partitions[i].nthreads; /* Initialize the threading stuff */ pok_partitions[i].mode = POK_PARTITION_MODE_INIT_WARM; #ifdef POK_NEEDS_LOCKOBJECTS pok_partitions[i].lockobj_index_low = lockobj_index; pok_partitions[i].lockobj_index_high = lockobj_index + ((uint8_t[]) POK_CONFIG_PARTITIONS_NLOCKOBJECTS[i]); pok_partitions[i].nlockobjs = ((uint8_t[]) POK_CONFIG_PARTITIONS_NLOCKOBJECTS[i]); lockobj_index = lockobj_index + pok_partitions[i].nlockobjs; /* Initialize mutexes stuff */ #endif #ifdef POK_NEEDS_ERROR_HANDLING pok_partitions[i].thread_error = 0; pok_partitions[i].error_status.failed_thread = 0; pok_partitions[i].error_status.failed_addr = 0; pok_partitions[i].error_status.error_kind = POK_ERROR_KIND_INVALID; pok_partitions[i].error_status.msg_size = 0; #endif pok_loader_load_partition (i, base_addr - base_vaddr, &program_entry); /* * Load the partition in its address space */ pok_partitions[i].thread_main_entry = program_entry; pok_partitions[i].lock_level = 0; pok_partitions[i].start_condition = NORMAL_START; #ifdef POK_NEEDS_INSTRUMENTATION pok_instrumentation_partition_archi (i); #endif pok_partition_setup_main_thread (i); pok_partitions[i].current_thread = pok_partitions[i].thread_main; } return POK_ERRNO_OK; }
void pok_loader_load_partition (const uint32_t part_id, uint32_t *entry) { (void) part_id; uint32_t part_entry; uint32_t segments; if(read_uint32(&part_entry) != sizeof(uint32_t)) { #ifdef POK_NEEDS_ERROR_HANDLING pok_partition_error (part_id, POK_ERROR_KIND_PARTITION_CONFIGURATION); #else #ifdef POK_NEEDS_DEBUG #include <core/debug.h> #include <stdio.h> pok_fatal ("No partition entry\n"); #endif #endif } if(read_uint32(&segments) != sizeof(uint32_t)) { #ifdef POK_NEEDS_ERROR_HANDLING pok_partition_error (part_id, POK_ERROR_KIND_PARTITION_CONFIGURATION); #else #ifdef POK_NEEDS_DEBUG #include <core/debug.h> #include <stdio.h> pok_fatal ("No partition size\n"); #endif #endif } #ifdef POK_NEEDS_DEBUG printf("[DEBUG]\t [Reading partition %d] Entry address: %p\n", part_id, (void*)(part_entry)); printf("[DEBUG]\t [Reading partition %d] Segments number: %d\n", part_id, segments); #endif unsigned int segment = 0; unsigned int part_size = 0; while (segment < segments) { uint32_t segment_address; uint32_t segment_size; if (read_uint32(&segment_address) != sizeof(uint32_t)) { #ifdef POK_NEEDS_ERROR_HANDLING pok_partition_error (part_id, POK_ERROR_KIND_PARTITION_CONFIGURATION); #else #ifdef POK_NEEDS_DEBUG #include <core/debug.h> #include <stdio.h> pok_fatal ("No segment address\n"); #endif #endif } #ifdef POK_NEEDS_DEBUG printf("[DEBUG]\t [Reading partition %d] Segment %d address: %p\n", part_id, segment, (void*)segment_address); #endif if (read_uint32(&segment_size) != sizeof(uint32_t)) { #ifdef POK_NEEDS_ERROR_HANDLING pok_partition_error (part_id, POK_ERROR_KIND_PARTITION_CONFIGURATION); #else #ifdef POK_NEEDS_DEBUG #include <core/debug.h> #include <stdio.h> pok_fatal ("No segment size\n"); #endif #endif } #ifdef POK_NEEDS_DEBUG printf("[DEBUG]\t [Reading partition %d] Segment %d size: %d\n", part_id, segment, segment_size); #endif if (read_data(segment_size, (char*)(segment_address)) != segment_size) { #ifdef POK_NEEDS_ERROR_HANDLING pok_partition_error (part_id, POK_ERROR_KIND_PARTITION_CONFIGURATION); #else #ifdef POK_NEEDS_DEBUG #include <core/debug.h> #include <stdio.h> printf("No segment data\n"); #endif #endif } part_size = part_size + segment_size; #ifdef POK_NEEDS_DEBUG printf("[DEBUG]\t [Reading partition %d] Segment %d loaded\n", part_id, segment); #endif segment++; } *entry = (uint32_t) (part_entry); }