aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuji Mano <yuji.mano@am.sony.com>2009-02-05 18:30:43 -0800
committerYuji Mano <yuji.mano@am.sony.com>2009-02-11 11:02:18 -0800
commitc5d91b1a18da4fbcb833809f163e9663c474cc9b (patch)
tree47dcd02cdd36e244f09609747e5ecfdc6df7ed15
parent0e5300b625de0b93cb11864fceffc275e0d546a0 (diff)
downloadmars-src-c5d91b1a18da4fbcb833809f163e9663c474cc9b.tar.gz
base: Cache workload module
This patch caches the currently loaded workload module info inside the kernel so the workload module only needs to be reloaded from shared storage to MPU storage if different from the one currently loaded in MPU storage. This patch adds kernel's custom version of memcmp/memcpy routines to keep code size to a minimum. Signed-off-by: Yuji Mano <yuji.mano@am.sony.com> Acked-by: Kazunori Asayama <asayama@sm.sony.co.jp>
-rw-r--r--base/src/mpu/kernel/kernel.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/base/src/mpu/kernel/kernel.c b/base/src/mpu/kernel/kernel.c
index 60a8667..e43e7ae 100644
--- a/base/src/mpu/kernel/kernel.c
+++ b/base/src/mpu/kernel/kernel.c
@@ -37,7 +37,6 @@
#include <stddef.h>
#include <stdint.h>
-#include <string.h>
#include <spu_mfcio.h>
#include "config.h"
@@ -70,10 +69,42 @@ static uint64_t workload_ea;
static struct mars_workload_context schedule_workload;
static uint16_t schedule_workload_id;
-/* module entry */
+/* workload module cached */
+static struct mars_workload_module cached_workload_module = {0, 0, 0, 0};
+
+/* workload module entry */
typedef void (*module_entry)(
const struct mars_kernel_syscalls *kernel_syscalls);
+static int kernel_memcmp(const void *s1, const void *s2, int size)
+{
+ unsigned char *ptr_1 = (unsigned char *)s1;
+ unsigned char *ptr_2 = (unsigned char *)s2;
+ unsigned char *ptr_e = (unsigned char *)ptr_1 + size;
+
+ while (ptr_1 < ptr_e) {
+ if (*ptr_1 != *ptr_2)
+ return 1;
+ ptr_1++;
+ ptr_2++;
+ }
+
+ return 0;
+}
+
+static void kernel_memcpy(void *dst, const void *src, int size)
+{
+ unsigned char *ptr_1 = (unsigned char *)dst;
+ unsigned char *ptr_2 = (unsigned char *)src;
+ unsigned char *ptr_e = (unsigned char *)ptr_1 + size;
+
+ while (ptr_1 < ptr_e) {
+ *ptr_1 = *ptr_2;
+ ptr_1++;
+ ptr_2++;
+ }
+}
+
static void dma_put(void *ls, uint64_t ea, uint32_t size)
{
mfc_put((volatile void *)ls, ea, size, MARS_KERNEL_DMA_TAG, 0, 0);
@@ -629,6 +660,35 @@ static void __attribute__((noinline)) run_workload(void)
((module_entry)workload.module.entry)(&kernel_syscalls);
}
+static void load_workload_module(void)
+{
+ __vector unsigned char *bss_ptr, *bss_end;
+
+ /* 0 the bss section */
+ bss_ptr = (__vector unsigned char *)(MARS_WORKLOAD_MODULE_BASE_ADDR +
+ workload.module.exec_size);
+ bss_end = (__vector unsigned char *)((void *)bss_ptr +
+ workload.module.bss_size);
+
+ while (bss_ptr < bss_end)
+ *bss_ptr++ = spu_splats((unsigned char)0);
+
+ /* only reload the workload module if different from cached */
+ if (kernel_memcmp(&cached_workload_module, &workload.module,
+ sizeof(struct mars_workload_module))) {
+ /* load the exec code into mpu storage from host storage */
+ dma_get((void *)MARS_WORKLOAD_MODULE_BASE_ADDR,
+ workload.module.exec_ea, workload.module.exec_size);
+
+ /* store the current cached workload module ea */
+ kernel_memcpy(&cached_workload_module, &workload.module,
+ sizeof(struct mars_workload_module));
+ }
+
+ /* sync before executing loaded code */
+ spu_sync();
+}
+
static int scheduler(void)
{
int status;
@@ -650,16 +710,8 @@ static int scheduler(void)
if (status == MARS_WORKLOAD_RESERVED_NONE)
return MARS_KERNEL_STATUS_IDLE;
- /* load the exec code into mpu storage from host storage */
- dma_get((void *)MARS_WORKLOAD_MODULE_BASE_ADDR,
- workload.module.exec_ea, workload.module.exec_size);
-
- /* 0 the bss section */
- memset((void *)MARS_WORKLOAD_MODULE_BASE_ADDR +
- workload.module.exec_size, 0, workload.module.bss_size);
-
- /* sync before executing loaded code */
- spu_sync();
+ /* load the workload module */
+ load_workload_module();
/* run workload */
run_workload();