[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