From 51f75d9ba8c7fbe6bf46e620e280c22af3a7f9ea Mon Sep 17 00:00:00 2001 From: "Balazs Gerofi bgerofi@riken.jp" Date: Thu, 27 Mar 2014 14:58:26 +0900 Subject: [PATCH 1/5] mcexec: options for target CPU core ID where application is executed --- executer/user/mcexec.c | 75 +++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 16 deletions(-) diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index 199804c7..c22b34de 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include "../include/uprotocol.h" @@ -564,6 +565,11 @@ static int reduce_stack(struct rlimit *orig_rlim, char *argv[]) return 1; } +void print_usage(char **argv) +{ + fprintf(stderr, "Usage: %s [-c target_core] [] (program) [args...]\n", argv[0]); +} + int main(int argc, char **argv) { // int fd; @@ -573,6 +579,7 @@ int main(int argc, char **argv) #endif FILE *fp; struct program_load_desc *desc; + int envs_len; char *envs; char *args; char dev[64]; @@ -587,6 +594,9 @@ int main(int argc, char **argv) struct rlimit rlim_stack; unsigned long lcur; unsigned long lmax; + int target_core = 0; + int mcosid = 0; + int opt; #ifdef USE_SYSCALL_MOD_CALL __glob_argc = argc; @@ -597,6 +607,10 @@ int main(int argc, char **argv) if (!altroot) { altroot = "/usr/linux-k1om-4.7/linux-k1om"; } + + /* Collect environment variables */ + envs_len = flatten_strings(-1, environ, &envs); + envs = envs; error = getrlimit(RLIMIT_STACK, &rlim_stack); if (error) { @@ -610,24 +624,52 @@ int main(int argc, char **argv) fprintf(stderr, "Error: Failed to reduce stack.\n"); return 1; } - - strcpy(dev, "/dev/mcos0"); - if(argv[1]){ - for(p = argv[1]; *p && *p >= '0' && *p <= '9'; p++); - if(!*p){ - sprintf(dev, "/dev/mcos%s", argv[1]); - for(a = argv + 2; *a; a++) - a[-1] = a[0]; - a[-1] = NULL; - argc--; + + /* Parse options ("+" denotes stop at the first non-option) */ + while ((opt = getopt(argc, argv, "+c:")) != -1) { + switch (opt) { + case 'c': + target_core = atoi(optarg); + break; + + default: /* '?' */ + print_usage(argv); + exit(EXIT_FAILURE); } } - if (argc < 2) { - fprintf(stderr, "Usage: %s [] (program) [args...]\n", - argv[0]); - return 1; + + if (optind >= argc) { + print_usage(argv); + exit(EXIT_FAILURE); } - + + /* Determine OS device */ + if (isdigit(*argv[optind])) { + mcosid = atoi(argv[optind]); + ++optind; + } + + sprintf(dev, "/dev/mcos%d", mcosid); + + /* No more arguments? */ + if (optind >= argc) { + print_usage(argv); + exit(EXIT_FAILURE); + } + + /* Shift arguments to the front */ + for (a = argv + optind; *a; a++) { + a[- optind + 1] = a[0]; + } + argv[optind + 2] = NULL; + argc -= (optind - 1); + + printf("target_core: %d, device: %s, command: ", target_core, dev); + for (i = 1; i < argc; ++i) { + printf("%s ", argv[i]); + } + printf("\n"); + fp = fopen(argv[1], "rb"); if (!fp) { fprintf(stderr, "Error: Failed to open %s\n", argv[1]); @@ -663,7 +705,7 @@ int main(int argc, char **argv) __dprintf("# of sections: %d\n", desc->num_sections); - desc->envs_len = flatten_strings(-1, environ, &envs); + desc->envs_len = envs_len; desc->envs = envs; //print_flat(envs); @@ -671,6 +713,7 @@ int main(int argc, char **argv) desc->args = args; //print_flat(args); + desc->cpu = target_core; p = getenv(rlimit_stack_envname); if (p) { errno = 0; From a2515747cf94e04862ce7abd3f22f02074aef15b Mon Sep 17 00:00:00 2001 From: "Balazs Gerofi bgerofi@riken.jp" Date: Thu, 27 Mar 2014 15:32:23 +0900 Subject: [PATCH 2/5] print CPU core ID in debug messages --- kernel/debug.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/debug.c b/kernel/debug.c index e3497d54..006a65bb 100644 --- a/kernel/debug.c +++ b/kernel/debug.c @@ -88,6 +88,7 @@ int kprintf(const char *format, ...) flags = ihk_mc_spinlock_lock(&kmsg_lock); /* Copy into the local buf */ + len = sprintf(buf, "[%3d]: ", ihk_mc_get_processor_id()); va_start(va, format); len += vsnprintf(buf + len, KPRINTF_LOCAL_BUF_LEN - len - 2, format, va); va_end(va); From 11ddbcf3c842de74e2c030817107c10b6ec8830f Mon Sep 17 00:00:00 2001 From: "Balazs Gerofi bgerofi@riken.jp" Date: Thu, 27 Mar 2014 15:35:42 +0900 Subject: [PATCH 3/5] wait only 10 secs in mcreboot-attached --- arch/x86/tools/mcreboot-attached-mic.sh.in | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/tools/mcreboot-attached-mic.sh.in b/arch/x86/tools/mcreboot-attached-mic.sh.in index 07ab608e..eb54950e 100755 --- a/arch/x86/tools/mcreboot-attached-mic.sh.in +++ b/arch/x86/tools/mcreboot-attached-mic.sh.in @@ -57,7 +57,7 @@ if [ "$1" == "-u" ]; then exit fi -wait_time=20 +wait_time=10 if [ "$modules_were_loaded" == "1" ]; then echo "waiting for ${wait_time} seconds: " >&2 @@ -78,7 +78,7 @@ fi for mod_path in "$KMODDIR/ihk.ko" "$KMODDIR/ihk_mic.ko" "$KMODDIR/mcctrl.ko"; do if insmod $mod_path; then - sleep 3 + sleep 1 echo "$mod_path inserted succesfully" >&2 else echo "ERROR: couldn't insert $mod_path" >&2 @@ -87,26 +87,26 @@ for mod_path in "$KMODDIR/ihk.ko" "$KMODDIR/ihk_mic.ko" "$KMODDIR/mcctrl.ko"; do if [ "$mod_path" == "$KMODDIR/ihk_mic.ko" ]; then echo "creating OS device" >&2 - sleep 2 + sleep 1 "$SBINDIR/ihkconfig" 0 create - sleep 2 + sleep 1 fi if [ "$mod_path" == "$KMODDIR/mcctrl.ko" ]; then if [ $# -gt 0 ]; then echo "setting kernel parameter to: \"$1\"" >&2 "$SBINDIR/ihkosctl" 0 kargs "$1" - sleep 2 + sleep 1 else echo "setting kernel parameter to: \"hidos\"" >&2 "$SBINDIR/ihkosctl" 0 kargs "hidos" - sleep 2 + sleep 1 fi echo "using kernel image: $KERNDIR/mckernel.img" >&2 "$SBINDIR/ihkosctl" 0 load "$KERNDIR/mckernel.img" - sleep 2 + sleep 1 echo "booting OS 0" >&2 "$SBINDIR/ihkosctl" 0 boot - sleep 2 + sleep 1 fi done From ccd770ba2441ec1c6f64978698a83ff97c781fce Mon Sep 17 00:00:00 2001 From: "Balazs Gerofi bgerofi@riken.jp" Date: Thu, 27 Mar 2014 19:31:42 +0900 Subject: [PATCH 4/5] use per-process wait queues for system call request processing in mcexec so that multiple processes can share the per-core system call channels --- executer/include/uprotocol.h | 1 + executer/kernel/control.c | 76 +++++++++++++++++++++++++++++++++--- executer/kernel/ikc.c | 12 ++++-- executer/kernel/mcctrl.h | 10 ++++- executer/kernel/syscall.c | 41 +++++++++++++++++-- executer/user/mcexec.c | 3 +- kernel/include/syscall.h | 1 + kernel/syscall.c | 10 ++++- 8 files changed, 138 insertions(+), 16 deletions(-) diff --git a/executer/include/uprotocol.h b/executer/include/uprotocol.h index 34247103..bcb2681f 100644 --- a/executer/include/uprotocol.h +++ b/executer/include/uprotocol.h @@ -93,6 +93,7 @@ struct syscall_request { struct syscall_wait_desc { unsigned long cpu; struct syscall_request sr; + int pid; }; struct syscall_load_desc { diff --git a/executer/kernel/control.c b/executer/kernel/control.c index 671b81a5..cfd03bf6 100644 --- a/executer/kernel/control.c +++ b/executer/kernel/control.c @@ -267,10 +267,37 @@ static long mcexec_get_cpu(ihk_os_t os) return info->n_cpus; } -int mcexec_syscall(struct mcctrl_channel *c, unsigned long arg) +int mcexec_syscall(struct mcctrl_channel *c, int pid, unsigned long arg) { + struct wait_queue_head_list_node *wqhln = NULL; + struct wait_queue_head_list_node *wqhln_iter; + unsigned long flags; + + /* Look up per-process wait queue head with pid */ + flags = ihk_ikc_spinlock_lock(&c->wq_list_lock); + list_for_each_entry(wqhln_iter, &c->wq_list, list) { + if (wqhln_iter->pid == pid) { + wqhln = wqhln_iter; + break; + } + } + + if (!wqhln) { +retry_alloc: + wqhln = kmalloc(sizeof(*wqhln), GFP_KERNEL); + if (!wqhln) { + printk("WARNING: coudln't alloc wait queue head, retrying..\n"); + goto retry_alloc; + } + + wqhln->pid = pid; + init_waitqueue_head(&wqhln->wq_syscall); + list_add_tail(&wqhln->list, &c->wq_list); + } + ihk_ikc_spinlock_unlock(&c->wq_list_lock, flags); + c->req = 1; - wake_up(&c->wq_syscall); + wake_up(&wqhln->wq_syscall); return 0; } @@ -287,16 +314,21 @@ int mcexec_wait_syscall(ihk_os_t os, struct syscall_wait_desc *__user req) struct syscall_wait_desc swd; struct mcctrl_channel *c; struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os); + struct wait_queue_head_list_node *wqhln; + struct wait_queue_head_list_node *wqhln_iter; + int ret = 0; + unsigned long irqflags; #ifndef DO_USER_MODE unsigned long s, w, d; #endif //printk("mcexec_wait_syscall swd=%p req=%p size=%d\n", &swd, req, sizeof(swd.cpu)); - if (copy_from_user(&swd, req, sizeof(swd.cpu))) { + if (copy_from_user(&swd, req, sizeof(swd))) { return -EFAULT; } -if(swd.cpu >= usrdata->num_channels)return -EINVAL; + if (swd.cpu >= usrdata->num_channels) + return -EINVAL; c = get_peer_channel(usrdata, current); if (c) { @@ -308,9 +340,43 @@ if(swd.cpu >= usrdata->num_channels)return -EINVAL; #ifdef DO_USER_MODE retry: - if (wait_event_interruptible(c->wq_syscall, c->req)) { + /* Prepare per-process wait queue head */ +retry_alloc: + wqhln = kmalloc(sizeof(*wqhln), GFP_KERNEL); + if (!wqhln) { + printk("WARNING: coudln't alloc wait queue head, retrying..\n"); + goto retry_alloc; + } + + wqhln->pid = swd.pid; + init_waitqueue_head(&wqhln->wq_syscall); + + irqflags = ihk_ikc_spinlock_lock(&c->wq_list_lock); + /* First see if there is one wait queue already */ + list_for_each_entry(wqhln_iter, &c->wq_list, list) { + if (wqhln_iter->pid == current->tgid) { + kfree(wqhln); + wqhln = wqhln_iter; + list_del(&wqhln->list); + printk("DEBUG: wait queue head was already available in syscall wait\n"); + break; + } + } + list_add_tail(&wqhln->list, &c->wq_list); + ihk_ikc_spinlock_unlock(&c->wq_list_lock, irqflags); + + ret = wait_event_interruptible(wqhln->wq_syscall, c->req); + + /* Remove per-process wait queue head */ + irqflags = ihk_ikc_spinlock_lock(&c->wq_list_lock); + list_del(&wqhln->list); + ihk_ikc_spinlock_unlock(&c->wq_list_lock, irqflags); + kfree(wqhln); + + if (ret) { return -EINTR; } + c->req = 0; #if 1 mb(); diff --git a/executer/kernel/ikc.c b/executer/kernel/ikc.c index 91e46647..2f263041 100644 --- a/executer/kernel/ikc.c +++ b/executer/kernel/ikc.c @@ -40,7 +40,7 @@ void mcexec_prepare_ack(ihk_os_t os, unsigned long arg, int err); static void mcctrl_ikc_init(ihk_os_t os, int cpu, unsigned long rphys, struct ihk_ikc_channel_desc *c); -int mcexec_syscall(struct mcctrl_channel *c, unsigned long arg); +int mcexec_syscall(struct mcctrl_channel *c, int pid, unsigned long arg); static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, void *__packet, void *__os) @@ -62,7 +62,7 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, break; case SCD_MSG_SYSCALL_ONESIDE: - mcexec_syscall(usrdata->channels + pisp->ref, pisp->arg); + mcexec_syscall(usrdata->channels + pisp->ref, pisp->pid, pisp->arg); break; } @@ -219,7 +219,9 @@ static int connect_handler(struct ihk_ikc_channel_info *param) return 1; } param->packet_handler = syscall_packet_handler; - init_waitqueue_head(&usrdata->channels[cpu].wq_syscall); + + INIT_LIST_HEAD(&usrdata->channels[cpu].wq_list); + spin_lock_init(&usrdata->channels[cpu].wq_list_lock); usrdata->channels[cpu].c = c; kprintf("syscall: MC CPU %d connected. c=%p\n", cpu, c); @@ -238,7 +240,9 @@ static int connect_handler2(struct ihk_ikc_channel_info *param) cpu = usrdata->num_channels - 1; param->packet_handler = syscall_packet_handler; - init_waitqueue_head(&usrdata->channels[cpu].wq_syscall); + + INIT_LIST_HEAD(&usrdata->channels[cpu].wq_list); + spin_lock_init(&usrdata->channels[cpu].wq_list_lock); usrdata->channels[cpu].c = c; kprintf("syscall: MC CPU %d connected. c=%p\n", cpu, c); diff --git a/executer/kernel/mcctrl.h b/executer/kernel/mcctrl.h index ce79fb90..e03978b6 100644 --- a/executer/kernel/mcctrl.h +++ b/executer/kernel/mcctrl.h @@ -56,6 +56,7 @@ struct ikc_scd_packet { int msg; int ref; + int pid; int err; unsigned long arg; }; @@ -88,6 +89,12 @@ struct syscall_params { unsigned long *doorbell_va; }; +struct wait_queue_head_list_node { + struct list_head list; + wait_queue_head_t wq_syscall; + int pid; +}; + struct mcctrl_channel { struct ihk_ikc_channel_desc *c; struct syscall_params param; @@ -95,7 +102,8 @@ struct mcctrl_channel { void *dma_buf; int req; - wait_queue_head_t wq_syscall; + struct list_head wq_list; + ihk_spinlock_t wq_list_lock; }; struct mcctrl_usrdata { diff --git a/executer/kernel/syscall.c b/executer/kernel/syscall.c index 2418b198..682e23bc 100644 --- a/executer/kernel/syscall.c +++ b/executer/kernel/syscall.c @@ -57,7 +57,7 @@ static long pager_call(ihk_os_t os, struct syscall_request *req); #ifdef SC_DEBUG -//static struct ihk_dma_request last_request; +static struct ihk_dma_request last_request; static void print_dma_lastreq(void) { @@ -215,7 +215,7 @@ static int remote_page_fault(struct mcctrl_usrdata *usrdata, void *fault_addr, u struct syscall_request *req; struct syscall_response *resp; int error; - + dprintk("remote_page_fault(%p,%p,%llx)\n", usrdata, fault_addr, reason); channel = get_peer_channel(usrdata, current); @@ -241,8 +241,43 @@ static int remote_page_fault(struct mcctrl_usrdata *usrdata, void *fault_addr, u resp->status = STATUS_PAGE_FAULT; for (;;) { + struct wait_queue_head_list_node *wqhln; + struct wait_queue_head_list_node *wqhln_iter; + unsigned long irqflags; + +retry_alloc: + wqhln = kmalloc(sizeof(*wqhln), GFP_KERNEL); + if (!wqhln) { + printk("WARNING: coudln't alloc wait queue head, retrying..\n"); + goto retry_alloc; + } + + /* Prepare per-process wait queue head */ + wqhln->pid = current->tgid; + init_waitqueue_head(&wqhln->wq_syscall); + + irqflags = ihk_ikc_spinlock_lock(&channel->wq_list_lock); + /* First see if there is a wait queue already */ + list_for_each_entry(wqhln_iter, &channel->wq_list, list) { + if (wqhln_iter->pid == current->tgid) { + kfree(wqhln); + wqhln = wqhln_iter; + list_del(&wqhln->list); + break; + } + } + list_add_tail(&wqhln->list, &channel->wq_list); + ihk_ikc_spinlock_unlock(&channel->wq_list_lock, irqflags); + /* wait for response */ - error = wait_event_interruptible(channel->wq_syscall, channel->req); + error = wait_event_interruptible(wqhln->wq_syscall, channel->req); + + /* Remove per-process wait queue head */ + irqflags = ihk_ikc_spinlock_lock(&channel->wq_list_lock); + list_del(&wqhln->list); + ihk_ikc_spinlock_unlock(&channel->wq_list_lock, irqflags); + kfree(wqhln); + if (error) { printk("remote_page_fault:interrupted. %d\n", error); goto out; diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index c22b34de..15bc344e 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -664,7 +664,7 @@ int main(int argc, char **argv) argv[optind + 2] = NULL; argc -= (optind - 1); - printf("target_core: %d, device: %s, command: ", target_core, dev); + __dprintf("target_core: %d, device: %s, command: ", target_core, dev); for (i = 1; i < argc; ++i) { printf("%s ", argv[i]); } @@ -966,6 +966,7 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock) struct timeval tv; w.cpu = cpu; + w.pid = getpid(); while (((ret = ioctl(fd, MCEXEC_UP_WAIT_SYSCALL, (unsigned long)&w)) == 0) || (ret == -1 && errno == EINTR)) { diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 68c26853..6a8c86ed 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -87,6 +87,7 @@ struct user_desc { struct ikc_scd_packet { int msg; int ref; + int pid; int err; unsigned long arg; }; diff --git a/kernel/syscall.c b/kernel/syscall.c index 515b9411..4c99860d 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -116,6 +116,9 @@ static void send_syscall(struct syscall_request *req, int cpu) scp = &get_cpu_local_var(0)->scp2; syscall_channel = get_cpu_local_var(0)->syscall_channel2; + + /* XXX: is this really going to work if multiple processes + * exit/receive signals at the same time?? */ cpu = num_processors; } else{ @@ -144,8 +147,9 @@ static void send_syscall(struct syscall_request *req, int cpu) #ifdef SYSCALL_BY_IKC packet.msg = SCD_MSG_SYSCALL_ONESIDE; packet.ref = cpu; - packet.arg = scp->request_rpa; - + packet.pid = cpu_local_var(current)->pid; + packet.arg = scp->request_rpa; + dkprintf("send syscall, nr: %d, pid: %d\n", req->number, packet.pid); ihk_ikc_send(syscall_channel, &packet, 0); #endif } @@ -186,6 +190,8 @@ long do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx, int cpu } if (res->status == STATUS_PAGE_FAULT) { + dkprintf("STATUS_PAGE_FAULT in syscall, pid: %d\n", + cpu_local_var(current)->pid); error = page_fault_process(get_cpu_local_var(cpu)->current, (void *)res->fault_address, res->fault_reason); From b01b31f04dd94139b243337f6fc276d77538cee2 Mon Sep 17 00:00:00 2001 From: "Balazs Gerofi bgerofi@riken.jp" Date: Fri, 28 Mar 2014 18:43:34 +0900 Subject: [PATCH 5/5] use GFP_ATOMIC in interrupt context --- executer/kernel/control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executer/kernel/control.c b/executer/kernel/control.c index cfd03bf6..f3f7e19f 100644 --- a/executer/kernel/control.c +++ b/executer/kernel/control.c @@ -284,7 +284,7 @@ int mcexec_syscall(struct mcctrl_channel *c, int pid, unsigned long arg) if (!wqhln) { retry_alloc: - wqhln = kmalloc(sizeof(*wqhln), GFP_KERNEL); + wqhln = kmalloc(sizeof(*wqhln), GFP_ATOMIC); if (!wqhln) { printk("WARNING: coudln't alloc wait queue head, retrying..\n"); goto retry_alloc;