[Cbe-oss-dev] [PATCH 17/23]MARS/task: elf loader update
Yuji Mano
yuji.mano at am.sony.com
Sat Mar 14 12:18:57 EST 2009
This patch updates the task elf loader so that it expects separate text and data
segments and the -N linker option is no longer required when compiling the task
elf. This change is to allow for optimizations when loading task elfs into MPU
storage.
Signed-off-by: Yuji Mano <yuji.mano at am.sony.com>
---
task/src/common/task_internal_types.h | 14 +-
task/src/host/lib/task.c | 160 ++++++++++++++++++++++++----------
task/src/mpu/module/task_module.c | 20 ++--
3 files changed, 138 insertions(+), 56 deletions(-)
--- a/task/src/common/task_internal_types.h
+++ b/task/src/common/task_internal_types.h
@@ -50,14 +50,18 @@
struct mars_task_context {
uint8_t workload_module[MARS_WORKLOAD_MODULE_SIZE];
- uint8_t pad[MARS_TASK_CONTEXT_SIZE - MARS_WORKLOAD_MODULE_SIZE - 108];
+ uint8_t pad[MARS_TASK_CONTEXT_SIZE - MARS_WORKLOAD_MODULE_SIZE - 128];
- int32_t exit_code; /* exit code */
- uint64_t exec_ea; /* ea of exec */
- uint32_t exec_size; /* text/data size of exec */
- uint32_t bss_size; /* bss size of exec */
+ uint64_t text_ea; /* ea of text segment */
+ uint64_t data_ea; /* ea of data segment */
+ uint32_t text_vaddr; /* vaddr of text segment */
+ uint32_t data_vaddr; /* vaddr of data segment */
+ uint32_t text_size; /* size of text segment */
+ uint32_t data_size; /* size of data segment */
+ uint32_t bss_size; /* size of bss segment */
uint32_t entry; /* entry address of exec */
uint32_t stack; /* stack pointer of exec */
+ uint32_t exit_code; /* exit code */
uint64_t context_save_area_ea; /* context save area */
uint32_t context_save_area_low_size; /* size of low save area */
uint32_t context_save_area_high_size; /* size of high save area */
--- a/task/src/host/lib/task.c
+++ b/task/src/host/lib/task.c
@@ -57,14 +57,105 @@ static uint64_t task_exit_code_ea(uint64
return task_ea + offsetof(struct mars_task_context, exit_code);
}
+static int task_map_elf(struct mars_task_context *task, const void *elf_image)
+{
+ int ret, i;
+ int text_found = 0;
+ int data_found = 0;
+ Elf32_Ehdr *ehdr;
+ Elf32_Phdr *phdr;
+
+ /* process elf header information */
+ ehdr = (Elf32_Ehdr *)elf_image;
+ phdr = (Elf32_Phdr *)((void *)ehdr + ehdr->e_phoff);
+
+ /* elf is not executable */
+ if (ehdr->e_type != ET_EXEC)
+ return MARS_ERROR_FORMAT;
+
+ /* iterate through program header segments */
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ /* readonly text segment */
+ if (phdr->p_type == PT_LOAD &&
+ phdr->p_flags == PF_R + PF_X &&
+ phdr->p_align == 0x80) {
+ /* make sure base addr is what we expect */
+ if (text_found ||
+ phdr->p_vaddr != MARS_TASK_BASE_ADDR ||
+ phdr->p_memsz != phdr->p_filesz) {
+ ret = MARS_ERROR_FORMAT;
+ goto error;
+ }
+
+ /* initialize the task context text info */
+ task->text_ea = mars_ea_map((void *)ehdr +
+ phdr->p_offset,
+ phdr->p_filesz);
+ if (!task->text_ea) {
+ ret = MARS_ERROR_MEMORY;
+ goto error;
+ }
+
+ task->text_vaddr = phdr->p_vaddr;
+ task->text_size = phdr->p_filesz;
+
+ /* make sure we only find 1 text segment */
+ text_found = 1;
+ /* read-write data segment */
+ } else if (phdr->p_type == PT_LOAD &&
+ phdr->p_flags == PF_R + PF_W &&
+ phdr->p_align == 0x80) {
+ if (data_found) {
+ ret = MARS_ERROR_FORMAT;
+ goto error;
+ }
+
+ task->data_ea = mars_ea_map((void *)ehdr +
+ phdr->p_offset,
+ phdr->p_filesz);
+ if (!task->data_ea) {
+ ret = MARS_ERROR_MEMORY;
+ goto error;
+ }
+
+ task->data_vaddr = phdr->p_vaddr;
+ task->data_size = phdr->p_filesz;
+ task->bss_size = phdr->p_memsz - phdr->p_filesz;
+
+ /* make sure we only find 1 data segment */
+ data_found = 1;
+ }
+
+ /* increment program header */
+ phdr = (void *)phdr + ehdr->e_phentsize;
+ }
+
+ /* make sure text and data segment is found */
+ if (!text_found || !data_found) {
+ ret = MARS_ERROR_FORMAT;
+ goto error;
+ }
+
+ /* set the entry point of execution */
+ task->entry = ehdr->e_entry;
+
+ return MARS_SUCCESS;
+
+error:
+ if (text_found)
+ mars_ea_unmap(task->text_ea, task->text_size);
+ if (data_found)
+ mars_ea_unmap(task->data_ea, task->data_size);
+
+ return ret;
+}
+
int mars_task_create(struct mars_context *mars,
struct mars_task_id *id_ret,
const char *name, const void *elf_image,
uint32_t context_save_size)
{
int ret;
- Elf32_Ehdr *ehdr;
- Elf32_Phdr *phdr;
uint16_t workload_id;
uint64_t workload_ea;
struct mars_task_context *task;
@@ -81,13 +172,6 @@ int mars_task_create(struct mars_context
if (context_save_size > MARS_TASK_CONTEXT_SAVE_SIZE_MAX)
return MARS_ERROR_PARAMS;
- /* process elf header information */
- ehdr = (Elf32_Ehdr *)elf_image;
- phdr = (Elf32_Phdr *)((void *)ehdr + ehdr->e_phoff);
-
- if (phdr->p_type != PT_LOAD || phdr->p_vaddr != MARS_TASK_BASE_ADDR)
- return MARS_ERROR_FORMAT;
-
/* begin process to add the task to the workload queue */
ret = mars_workload_queue_add_begin(mars, &workload_id, &workload_ea,
mars_task_module_entry,
@@ -100,16 +184,12 @@ int mars_task_create(struct mars_context
MARS_TASK_CONTEXT_ALIGN,
MARS_TASK_CONTEXT_SIZE);
- /* initialize the task elf parameters */
- task->exec_size = phdr->p_filesz;
- task->exec_ea = mars_ea_map((void *)ehdr + phdr->p_offset,
- task->exec_size);
- if (!task->exec_ea) {
- ret = MARS_ERROR_MEMORY;
- goto error_map_exec;
+ /* map task ELF */
+ ret = task_map_elf(task, elf_image);
+ if (ret != MARS_SUCCESS) {
+ mars_workload_queue_add_cancel(mars, workload_id);
+ return ret;
}
- task->bss_size = phdr->p_memsz - phdr->p_filesz;
- task->entry = ehdr->e_entry;
/* initialize task id */
task->id.mars_context_ea = mars_ptr_to_ea(mars);
@@ -123,43 +203,34 @@ int mars_task_create(struct mars_context
task->exit_code = 0;
/* no context save - run complete */
- if (!context_save_size) {
+ if (context_save_size) {
+ /* allocate context save area */
+ task->context_save_area_ea =
+ mars_ea_memalign(MARS_TASK_CONTEXT_SAVE_ALIGN,
+ context_save_size);
+ if (!task->context_save_area_ea) {
+ mars_workload_queue_add_cancel(mars, workload_id);
+ return MARS_ERROR_MEMORY;
+ }
+ } else
task->context_save_area_ea = 0;
- goto done;
- }
-
- /* allocate context save area */
- task->context_save_area_ea =
- mars_ea_memalign(MARS_TASK_CONTEXT_SAVE_ALIGN,
- context_save_size);
- if (!task->context_save_area_ea) {
- ret = MARS_ERROR_MEMORY;
- goto error_malloc_context_save_area;
- }
-done:
/* update task context on EA */
mars_ea_put(workload_ea, task, MARS_TASK_CONTEXT_SIZE);
mars_ea_sync();
/* end process to add the task to the workload queue */
ret = mars_workload_queue_add_end(mars, workload_id);
- if (ret != MARS_SUCCESS)
- goto error_workload_queue_add_end;
+ if (ret != MARS_SUCCESS) {
+ mars_ea_free(task->context_save_area_ea);
+ mars_workload_queue_add_cancel(mars, workload_id);
+ return ret;
+ }
/* return id to caller */
*id_ret = task->id;
return MARS_SUCCESS;
-
-error_workload_queue_add_end:
- mars_ea_free(task->context_save_area_ea);
-error_malloc_context_save_area:
- mars_ea_unmap(task->exec_ea, task->exec_size);
-error_map_exec:
- mars_workload_queue_add_cancel(mars, workload_id);
-
- return ret;
}
int mars_task_destroy(struct mars_task_id *id)
@@ -196,8 +267,9 @@ int mars_task_destroy(struct mars_task_i
if (task->context_save_area_ea)
mars_ea_free(task->context_save_area_ea);
- /* unmap ELFs */
- mars_ea_unmap(task->exec_ea, task->exec_size);
+ /* unmap task ELF */
+ mars_ea_unmap(task->text_ea, task->text_size);
+ mars_ea_unmap(task->data_ea, task->data_size);
/* end process to remove the task from the workload queue */
ret = mars_workload_queue_remove_end(mars, id->workload_id);
--- a/task/src/mpu/module/task_module.c
+++ b/task/src/mpu/module/task_module.c
@@ -443,18 +443,24 @@ static void context_start(void)
{
__vector unsigned char *bss_ptr, *bss_end;
+ /* only reload the readonly text segment if different from cached */
+ if (!task_cached)
+ mars_module_dma_get((void *)task->text_vaddr, task->text_ea,
+ task->text_size, MARS_TASK_MODULE_DMA_TAG);
+
+ /* load the read-write data segment */
+ mars_module_dma_get((void *)task->data_vaddr, task->data_ea,
+ task->data_size, MARS_TASK_MODULE_DMA_TAG);
+
/* 0 the bss section */
- bss_ptr = (__vector unsigned char *)
- (MARS_TASK_BASE_ADDR + task->exec_size);
- bss_end = (__vector unsigned char *)
- ((void *)bss_ptr + task->bss_size);
+ bss_ptr = (__vector unsigned char *)(task->data_vaddr +
+ task->data_size);
+ bss_end = (__vector unsigned char *)((void *)bss_ptr +
+ task->bss_size);
while (bss_ptr < bss_end)
*bss_ptr++ = spu_splats((unsigned char)0);
- /* dma the text and data section */
- mars_module_dma_get((void *)MARS_TASK_BASE_ADDR, task->exec_ea,
- task->exec_size, MARS_TASK_MODULE_DMA_TAG);
mars_module_dma_wait(MARS_TASK_MODULE_DMA_TAG);
/* sync before executing loaded code */
More information about the cbe-oss-dev
mailing list