diff --git a/kernel/debug.c b/kernel/debug.c index 8ed287d5..1d5c8026 100644 --- a/kernel/debug.c +++ b/kernel/debug.c @@ -49,7 +49,7 @@ int __kprintf(const char *format, ...) /* Copy into the local buf */ va_start(va, format); - len += vsnprintf(buf + len, KPRINTF_LOCAL_BUF_LEN - len, format, va); + len += vsnprintf(buf + len, KPRINTF_LOCAL_BUF_LEN - len - 2, format, va); va_end(va); /* Append to kmsg buffer */ @@ -74,7 +74,7 @@ int kprintf(const char *format, ...) /* Copy into the local buf */ va_start(va, format); - len += vsnprintf(buf + len, KPRINTF_LOCAL_BUF_LEN - len, format, va); + len += vsnprintf(buf + len, KPRINTF_LOCAL_BUF_LEN - len - 2, format, va); va_end(va); /* Append to kmsg buffer */ diff --git a/kernel/host.c b/kernel/host.c index ebc13a3c..3c0c82cb 100644 --- a/kernel/host.c +++ b/kernel/host.c @@ -28,6 +28,11 @@ static void process_msg_prepare_process(unsigned long rphys) int i, npages, n; struct process *proc; unsigned long addr; + char *args_envs, *args_envs_r; + unsigned long args_envs_p, args_envs_rp; + char **argv; + int argc, envc, args_envs_npages; + char **env; sz = sizeof(struct program_load_desc) + sizeof(struct program_image_section) * 16; @@ -97,8 +102,89 @@ static void process_msg_prepare_process(unsigned long rphys) cpu_local_var(scp).response_pa, VR_RESERVED); + /* Map, copy and update args and envs */ + addr = e; + e = addr + PAGE_SIZE * ARGENV_PAGE_COUNT; + + args_envs = aal_mc_alloc_pages(ARGENV_PAGE_COUNT, 0); + args_envs_p = virt_to_phys(args_envs); + + add_process_memory_range(proc, addr, e, + args_envs_p, + VR_RESERVED); + + dkprintf("args_envs mapping\n"); + + dkprintf("args: 0x%lX, args_len: %d\n", p->args, p->args_len); + + // Map in remote physical addr of args and copy it + args_envs_npages = (p->args_len + PAGE_SIZE - 1) >> PAGE_SHIFT; + dkprintf("args_envs_npages: %d\n", args_envs_npages); + args_envs_rp = aal_mc_map_memory(NULL, (unsigned long)p->args, p->args_len); + dkprintf("args_envs_rp: 0x%lX\n", args_envs_rp); + args_envs_r = (char *)aal_mc_map_virtual(args_envs_rp, args_envs_npages, + PTATTR_WRITABLE); + dkprintf("args_envs_r: 0x%lX\n", args_envs_r); + + dkprintf("args copy, nr: %d\n", *((int*)args_envs_r)); + + memcpy_long(args_envs, args_envs_r, p->args_len + 8); + + /* TODO: add a virtual_unmap function, that really does only unmap + * the virtual address and doesn't drop the physical page itself!! */ + + //aal_mc_unmap_virtual(args_envs_r, args_envs_npages); + //aal_mc_unmap_memory(NULL, args_envs_rp, p->args_len); + + dkprintf("envs: 0x%lX, envs_len: %d\n", p->envs, p->envs_len); + + // Map in remote physical addr of envs and copy it after args + args_envs_npages = (p->envs_len + PAGE_SIZE - 1) >> PAGE_SHIFT; + dkprintf("args_envs_npages: %d\n", args_envs_npages); + args_envs_rp = aal_mc_map_memory(NULL, (unsigned long)p->envs, p->envs_len); + dkprintf("args_envs_rp: 0x%lX\n", args_envs_rp); + args_envs_r = (char *)aal_mc_map_virtual(args_envs_rp, args_envs_npages, + PTATTR_WRITABLE); + dkprintf("args_envs_r: 0x%lX\n", args_envs_r); + + dkprintf("envs copy, nr: %d\n", *((int*)args_envs_r)); + + memcpy_long(args_envs + p->args_len, args_envs_r, p->envs_len + 8); + + //aal_mc_unmap_virtual(args_envs_r, args_envs_npages); + //aal_mc_unmap_memory(NULL, args_envs_rp, p->envs_len); + + // Update variables + argc = *((int*)(args_envs)); + dkprintf("argc: %d\n", argc); + + argv = (char **)(args_envs + (sizeof(int))); + while (*argv) { + char **_argv = argv; + dkprintf("%s\n", args_envs + (unsigned long)*argv); + *argv = (char *)addr + (unsigned long)*argv; // Process' address space! + argv = ++_argv; + } + argv = (char **)(args_envs + (sizeof(int))); + + envc = *((int*)(args_envs + p->args_len)); + dkprintf("envc: %d\n", envc); + + env = (char **)(args_envs + p->args_len + sizeof(int)); + while (*env) { + char **_env = env; + //dkprintf("%s\n", args_envs + p->args_len + (unsigned long)*env); + *env = (char *)addr + p->args_len + (unsigned long)*env; + env = ++_env; + } + env = (char **)(args_envs + p->args_len + sizeof(int)); + + dkprintf("env OK\n"); + + aal_mc_unmap_virtual(args_envs, ARGENV_PAGE_COUNT); + p->rprocess = (unsigned long)proc; - init_process_stack(proc); + init_process_stack(proc, argc, argv, envc, env); dkprintf("new process : %p [%d] / table : %p\n", proc, proc->pid, proc->vm->page_table); diff --git a/kernel/include/process.h b/kernel/include/process.h index e081ee21..07c11b79 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -83,7 +83,8 @@ int add_process_memory_range(struct process *process, unsigned long phys, unsigned long flag); int remove_process_region(struct process *proc, unsigned long start, unsigned long end); -void init_process_stack(struct process *process); +void init_process_stack(struct process *process, int argc, char **argv, + int envc, char **env); unsigned long extend_process_region(struct process *proc, unsigned long start, unsigned long end, unsigned long address); diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 55cfea0d..617c51cc 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -8,8 +8,9 @@ #define REQUEST_PAGE_COUNT 16 #define RESPONSE_PAGE_COUNT 16 #define DOORBELL_PAGE_COUNT 1 +#define ARGENV_PAGE_COUNT 8 #define SCD_RESERVED_COUNT \ - (REQUEST_PAGE_COUNT + RESPONSE_PAGE_COUNT + DOORBELL_PAGE_COUNT) + (REQUEST_PAGE_COUNT + RESPONSE_PAGE_COUNT + DOORBELL_PAGE_COUNT + ARGENV_PAGE_COUNT) #define SCD_MSG_PREPARE_PROCESS 0x1 #define SCD_MSG_PREPARE_PROCESS_ACKED 0x2 @@ -89,6 +90,10 @@ struct program_load_desc { int pid; unsigned long entry; unsigned long rprocess; + char *args; + unsigned long args_len; + char *envs; + unsigned long envs_len; struct program_image_section sections[0]; }; diff --git a/kernel/process.c b/kernel/process.c index e36e86df..0238e8f9 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -17,7 +17,7 @@ #define USER_STACK_NR_PAGES 4 -#define KERNEL_STACK_NR_PAGES 4 +#define KERNEL_STACK_NR_PAGES 8 extern long do_arch_prctl(unsigned long code, unsigned long address); @@ -137,8 +137,11 @@ int add_process_memory_range(struct process *process, -void init_process_stack(struct process *process) +void init_process_stack(struct process *process, int argc, char **argv, + int envc, char **env) { + int s_ind = 0; + int arg_ind; char *stack = aal_mc_alloc_pages(USER_STACK_NR_PAGES, 0); unsigned long *p = (unsigned long *)(stack + (USER_STACK_NR_PAGES * PAGE_SIZE)); @@ -150,19 +153,24 @@ void init_process_stack(struct process *process) USER_END, virt_to_phys(stack), VR_STACK); - /* TODO: fill with actual value of argc, argv, envp */ p[-1] = 0; /* AT_NULL */ p[-2] = 0; p[-3] = USER_END - sizeof(unsigned long) * 2; - p[-4] = 0; /* env: "" */ - p[-5] = 0x41; /* argv(0): "a" */ - p[-6] = 0; /* envp: NULL */ - p[-7] = 0; /* argv[1] = NULL */ - p[-8] = USER_END - sizeof(unsigned long) * 5; /* argv[0] = END - 16 */ - p[-9] = 1; /* argc */ + p[-4] = 0; /* envp terminating NULL */ + s_ind = -5; + for (arg_ind = envc - 1; arg_ind > -1; --arg_ind) { + p[s_ind--] = (unsigned long)env[arg_ind]; + } + + p[s_ind--] = 0; /* argv terminating NULL */ + for (arg_ind = argc - 1; arg_ind > -1; --arg_ind) { + p[s_ind--] = (unsigned long)argv[arg_ind]; + } + /* argc */ + p[s_ind] = argc; aal_mc_modify_user_context(process->uctx, AAL_UCR_STACK_POINTER, - USER_END - sizeof(unsigned long) * 9); + USER_END + sizeof(unsigned long) * s_ind); process->vm->region.stack_end = USER_END; process->vm->region.stack_start = USER_END - (USER_STACK_NR_PAGES * PAGE_SIZE); diff --git a/linux/executer/mcexec.c b/linux/executer/mcexec.c index 42545212..10966467 100644 --- a/linux/executer/mcexec.c +++ b/linux/executer/mcexec.c @@ -191,12 +191,88 @@ void print_desc(struct program_load_desc *desc) unsigned long dma_buf_pa; + +void print_flat(char *flat) +{ + char **string; + + printf("counter: %d\n", *((int *)flat)); + + string = (char **)(flat + sizeof(int)); + while (*string) { + + printf("%s\n", (flat + (unsigned long)(*string))); + + ++string; + } +} + +/* + * Flatten out a (char **) string array into the following format: + * [nr_strings][char *offset of string_0]...[char *offset of string_n-1][NULL][string0]...[stringn_1] + * if nr_strings == -1, we assume the last item is NULL + * + * NOTE: copy this string somewhere, add the address of the string to each offset + * and we get back a valid argv or envp array. + * + * returns the total length of the flat string and updates flat to + * point to the beginning. + */ +int flatten_strings(int nr_strings, char **strings, char **flat) +{ + int full_len, string_i; + unsigned int flat_offset; + char *string; + char *_flat; + + /* How many strings do we have? */ + if (nr_strings == -1) { + for (nr_strings = 0; strings[nr_strings]; ++nr_strings); + } + + /* Count full length */ + full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL + for (string_i = 0; string_i < nr_strings; ++string_i) { + // Pointer + actual value + full_len += sizeof(char *) + strlen(strings[string_i]) + 1; + } + + _flat = (char *)malloc(full_len); + if (!_flat) { + return 0; + } + + memset(_flat, 0, full_len); + + /* Number of strings */ + *((int*)_flat) = nr_strings; + + // Actual offset + flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1); + + for (string_i = 0; string_i < nr_strings; ++string_i) { + + /* Fabricate the string */ + *((char **)(_flat + sizeof(int) + string_i * sizeof(char *))) = (void *)flat_offset; + memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1); + flat_offset += strlen(strings[string_i]) + 1; + + } + + *flat = _flat; + return full_len; +} + + int main(int argc, char **argv) { int fd, fdm; FILE *fp; struct program_load_desc *desc; long r; + char *envs; + char *args; + int len; if (argc < 2) { fprintf(stderr, "Usage: %s (program) [args...]\n", @@ -217,6 +293,14 @@ int main(int argc, char **argv) } __dprintf("# of sections: %d\n", desc->num_sections); + + desc->envs_len = flatten_strings(-1, environ, &envs); + desc->envs = envs; + //print_flat(envs); + + desc->args_len = flatten_strings(-1, argv + 1, &args); + desc->args = args; + //print_flat(args); fd = open("/dev/mcos0", O_RDWR); if (fd < 0) { diff --git a/linux/include/uprotocol.h b/linux/include/uprotocol.h index aa9a8451..4d9a4656 100644 --- a/linux/include/uprotocol.h +++ b/linux/include/uprotocol.h @@ -31,6 +31,10 @@ struct program_load_desc { int pid; unsigned long entry; unsigned long rprocess; + char *args; + unsigned long args_len; + char *envs; + unsigned long envs_len; struct program_image_section sections[0]; }; diff --git a/linux/mod_mcctrl/control.c b/linux/mod_mcctrl/control.c index 5d5ef9b8..597cf2e9 100644 --- a/linux/mod_mcctrl/control.c +++ b/linux/mod_mcctrl/control.c @@ -24,6 +24,7 @@ static long mcexec_prepare_image(aal_os_t os, { struct program_load_desc desc, *pdesc; struct ikc_scd_packet isp; + void *args, *envs; if (copy_from_user(&desc, udesc, sizeof(struct program_load_desc))) { @@ -46,6 +47,28 @@ static long mcexec_prepare_image(aal_os_t os, pdesc->pid = task_tgid_vnr(current); + args = kmalloc(pdesc->args_len, GFP_KERNEL); + if (copy_from_user(args, pdesc->args, pdesc->args_len)) { + kfree(args); + kfree(pdesc); + return -EFAULT; + } + + envs = kmalloc(pdesc->envs_len, GFP_KERNEL); + if (copy_from_user(envs, pdesc->envs, pdesc->envs_len)) { + kfree(envs); + kfree(args); + kfree(pdesc); + return -EFAULT; + } + + pdesc->args = virt_to_phys(args); + printk("args: 0x%lX\n", pdesc->args); + printk("argc: %d\n", *(int*)args); + pdesc->envs = virt_to_phys(envs); + printk("envs: 0x%lX\n", pdesc->envs); + printk("envc: %d\n", *(int*)envs); + isp.msg = SCD_MSG_PREPARE_PROCESS; isp.ref = pdesc->cpu; isp.arg = virt_to_phys(pdesc); @@ -62,6 +85,8 @@ static long mcexec_prepare_image(aal_os_t os, sizeof(struct program_image_section) * desc.num_sections); kfree(pdesc); + kfree(envs); + kfree(args); return 0; }