mcctrl: refcount per-process data to avoid corrupted syscall request lists
This commit is contained in:
@@ -127,7 +127,7 @@ static long mcexec_prepare_image(ihk_os_t os,
|
|||||||
printk("%s: ERROR: # of sections: %d\n",
|
printk("%s: ERROR: # of sections: %d\n",
|
||||||
__FUNCTION__, num_sections);
|
__FUNCTION__, num_sections);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto free_out;
|
goto put_and_free_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdesc = kmalloc(sizeof(struct program_load_desc) +
|
pdesc = kmalloc(sizeof(struct program_load_desc) +
|
||||||
@@ -139,7 +139,7 @@ static long mcexec_prepare_image(ihk_os_t os,
|
|||||||
sizeof(struct program_image_section)
|
sizeof(struct program_image_section)
|
||||||
* num_sections)) {
|
* num_sections)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto free_out;
|
goto put_and_free_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(desc);
|
kfree(desc);
|
||||||
@@ -149,19 +149,19 @@ static long mcexec_prepare_image(ihk_os_t os,
|
|||||||
|
|
||||||
if (reserve_user_space(usrdata, &pdesc->user_start, &pdesc->user_end)) {
|
if (reserve_user_space(usrdata, &pdesc->user_start, &pdesc->user_end)) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_out;
|
goto put_and_free_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
args = kmalloc(pdesc->args_len, GFP_KERNEL);
|
args = kmalloc(pdesc->args_len, GFP_KERNEL);
|
||||||
if (copy_from_user(args, pdesc->args, pdesc->args_len)) {
|
if (copy_from_user(args, pdesc->args, pdesc->args_len)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto free_out;
|
goto put_and_free_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
envs = kmalloc(pdesc->envs_len, GFP_KERNEL);
|
envs = kmalloc(pdesc->envs_len, GFP_KERNEL);
|
||||||
if (copy_from_user(envs, pdesc->envs, pdesc->envs_len)) {
|
if (copy_from_user(envs, pdesc->envs, pdesc->envs_len)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto free_out;
|
goto put_and_free_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdesc->args = (void*)virt_to_phys(args);
|
pdesc->args = (void*)virt_to_phys(args);
|
||||||
@@ -185,7 +185,7 @@ static long mcexec_prepare_image(ihk_os_t os,
|
|||||||
|
|
||||||
if (pdesc->err < 0) {
|
if (pdesc->err < 0) {
|
||||||
ret = pdesc->err;
|
ret = pdesc->err;
|
||||||
goto free_out;
|
goto put_and_free_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update rpgtable */
|
/* Update rpgtable */
|
||||||
@@ -194,7 +194,7 @@ static long mcexec_prepare_image(ihk_os_t os,
|
|||||||
if (copy_to_user(udesc, pdesc, sizeof(struct program_load_desc) +
|
if (copy_to_user(udesc, pdesc, sizeof(struct program_load_desc) +
|
||||||
sizeof(struct program_image_section) * num_sections)) {
|
sizeof(struct program_image_section) * num_sections)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto free_out;
|
goto put_and_free_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintk("%s: pid %d, rpgtable: 0x%lx added\n",
|
dprintk("%s: pid %d, rpgtable: 0x%lx added\n",
|
||||||
@@ -202,6 +202,8 @@ static long mcexec_prepare_image(ihk_os_t os,
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
put_and_free_out:
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
free_out:
|
free_out:
|
||||||
kfree(args);
|
kfree(args);
|
||||||
kfree(pdesc);
|
kfree(pdesc);
|
||||||
@@ -428,7 +430,7 @@ static long mcexec_send_signal(ihk_os_t os, struct signal_desc *sigparam)
|
|||||||
isp.pid = sig.pid;
|
isp.pid = sig.pid;
|
||||||
isp.arg = virt_to_phys(msigp);
|
isp.arg = virt_to_phys(msigp);
|
||||||
|
|
||||||
if((rc = mcctrl_ikc_send(os, sig.cpu, &isp)) < 0){
|
if ((rc = mcctrl_ikc_send(os, sig.cpu, &isp)) < 0) {
|
||||||
printk("mcexec_send_signal: mcctrl_ikc_send ret=%d\n", rc);
|
printk("mcexec_send_signal: mcctrl_ikc_send ret=%d\n", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -504,7 +506,8 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
|
|||||||
|
|
||||||
if (copy_from_user(&req, (void *)arg, sizeof(req))) {
|
if (copy_from_user(&req, (void *)arg, sizeof(req))) {
|
||||||
printk("%s: error copying user request\n", __FUNCTION__);
|
printk("%s: error copying user request\n", __FUNCTION__);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto put_and_unlock_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&pe->lock);
|
mutex_lock(&pe->lock);
|
||||||
@@ -526,7 +529,7 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
|
|||||||
" doesn't match current partitioned execution\n",
|
" doesn't match current partitioned execution\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock_out;
|
goto put_and_unlock_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
--pe->nr_processes_left;
|
--pe->nr_processes_left;
|
||||||
@@ -543,7 +546,7 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
|
|||||||
printk("%s: error: no more CPUs available\n",
|
printk("%s: error: no more CPUs available\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock_out;
|
goto put_and_unlock_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_set(cpu, cpus_used);
|
cpu_set(cpu, cpus_used);
|
||||||
@@ -568,7 +571,7 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
|
|||||||
printk("%s: error: couldn't find CPU topology info\n",
|
printk("%s: error: couldn't find CPU topology info\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock_out;
|
goto put_and_unlock_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a core sharing the same cache iterating caches from
|
/* Find a core sharing the same cache iterating caches from
|
||||||
@@ -613,7 +616,7 @@ static long mcexec_get_cpuset(ihk_os_t os, unsigned long arg)
|
|||||||
printk("%s: error: no more CPUs available\n",
|
printk("%s: error: no more CPUs available\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock_out;
|
goto put_and_unlock_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_set(cpu, cpus_used);
|
cpu_set(cpu, cpus_used);
|
||||||
@@ -632,7 +635,7 @@ next_cpu:
|
|||||||
req.cpu_set_size : sizeof(cpus_to_use)))) {
|
req.cpu_set_size : sizeof(cpus_to_use)))) {
|
||||||
printk("%s: error copying mask to user\n", __FUNCTION__);
|
printk("%s: error copying mask to user\n", __FUNCTION__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock_out;
|
goto put_and_unlock_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu = cpumask_next(-1, &cpus_to_use);
|
cpu = cpumask_next(-1, &cpus_to_use);
|
||||||
@@ -640,7 +643,7 @@ next_cpu:
|
|||||||
printk("%s: error copying target core to user\n",
|
printk("%s: error copying target core to user\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock_out;
|
goto put_and_unlock_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save in per-process structure */
|
/* Save in per-process structure */
|
||||||
@@ -661,7 +664,8 @@ next_cpu:
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
unlock_out:
|
put_and_unlock_out:
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
mutex_unlock(&pe->lock);
|
mutex_unlock(&pe->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -691,34 +695,10 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mcctrl_delete_per_proc_data(struct mcctrl_usrdata *ud, int pid)
|
|
||||||
{
|
|
||||||
struct mcctrl_per_proc_data *ppd_iter, *ppd = NULL;
|
|
||||||
int hash = (pid & MCCTRL_PER_PROC_DATA_HASH_MASK);
|
|
||||||
int ret = 0;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
write_lock_irqsave(&ud->per_proc_data_hash_lock[hash], flags);
|
/* NOTE: per-process data is refcounted.
|
||||||
list_for_each_entry(ppd_iter, &ud->per_proc_data_hash[hash], hash) {
|
* For every get call the user should call put. */
|
||||||
if (ppd_iter->pid == pid) {
|
struct mcctrl_per_proc_data *mcctrl_get_per_proc_data(
|
||||||
ppd = ppd_iter;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ppd) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_del(&ppd->hash);
|
|
||||||
|
|
||||||
out:
|
|
||||||
write_unlock_irqrestore(&ud->per_proc_data_hash_lock[hash], flags);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline struct mcctrl_per_proc_data *mcctrl_get_per_proc_data(
|
|
||||||
struct mcctrl_usrdata *ud, int pid)
|
struct mcctrl_usrdata *ud, int pid)
|
||||||
{
|
{
|
||||||
struct mcctrl_per_proc_data *ppd_iter, *ppd = NULL;
|
struct mcctrl_per_proc_data *ppd_iter, *ppd = NULL;
|
||||||
@@ -727,7 +707,6 @@ inline struct mcctrl_per_proc_data *mcctrl_get_per_proc_data(
|
|||||||
|
|
||||||
/* Check if data for this process exists and return it */
|
/* Check if data for this process exists and return it */
|
||||||
read_lock_irqsave(&ud->per_proc_data_hash_lock[hash], flags);
|
read_lock_irqsave(&ud->per_proc_data_hash_lock[hash], flags);
|
||||||
|
|
||||||
list_for_each_entry(ppd_iter, &ud->per_proc_data_hash[hash], hash) {
|
list_for_each_entry(ppd_iter, &ud->per_proc_data_hash[hash], hash) {
|
||||||
if (ppd_iter->pid == pid) {
|
if (ppd_iter->pid == pid) {
|
||||||
ppd = ppd_iter;
|
ppd = ppd_iter;
|
||||||
@@ -735,10 +714,38 @@ inline struct mcctrl_per_proc_data *mcctrl_get_per_proc_data(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ppd) {
|
||||||
|
atomic_inc(&ppd->refcount);
|
||||||
|
}
|
||||||
|
|
||||||
read_unlock_irqrestore(&ud->per_proc_data_hash_lock[hash], flags);
|
read_unlock_irqrestore(&ud->per_proc_data_hash_lock[hash], flags);
|
||||||
|
|
||||||
return ppd;
|
return ppd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Drop reference. If zero, remove and deallocate */
|
||||||
|
void mcctrl_put_per_proc_data(struct mcctrl_per_proc_data *ppd)
|
||||||
|
{
|
||||||
|
int hash;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (!ppd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!atomic_dec_and_test(&ppd->refcount))
|
||||||
|
return;
|
||||||
|
|
||||||
|
dprintk("%s: deallocating PPD for pid %d\n", __FUNCTION__, ppd->pid);
|
||||||
|
hash = (ppd->pid & MCCTRL_PER_PROC_DATA_HASH_MASK);
|
||||||
|
|
||||||
|
write_lock_irqsave(&ppd->ud->per_proc_data_hash_lock[hash], flags);
|
||||||
|
list_del(&ppd->hash);
|
||||||
|
write_unlock_irqrestore(&ppd->ud->per_proc_data_hash_lock[hash], flags);
|
||||||
|
|
||||||
|
kfree(ppd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called indirectly from the IKC message handler.
|
* Called indirectly from the IKC message handler.
|
||||||
*/
|
*/
|
||||||
@@ -751,7 +758,7 @@ int mcexec_syscall(struct mcctrl_usrdata *ud, struct ikc_scd_packet *packet)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct mcctrl_per_proc_data *ppd;
|
struct mcctrl_per_proc_data *ppd;
|
||||||
|
|
||||||
/* Look up per-process structure */
|
/* Get a reference to per-process structure */
|
||||||
ppd = mcctrl_get_per_proc_data(ud, pid);
|
ppd = mcctrl_get_per_proc_data(ud, pid);
|
||||||
|
|
||||||
if (unlikely(!ppd)) {
|
if (unlikely(!ppd)) {
|
||||||
@@ -816,8 +823,10 @@ retry_alloc:
|
|||||||
|
|
||||||
wqhln->packet = packet;
|
wqhln->packet = packet;
|
||||||
wqhln->req = 1;
|
wqhln->req = 1;
|
||||||
wake_up(&wqhln->wq_syscall);
|
|
||||||
ihk_ikc_spinlock_unlock(&ppd->wq_list_lock, flags);
|
ihk_ikc_spinlock_unlock(&ppd->wq_list_lock, flags);
|
||||||
|
wake_up(&wqhln->wq_syscall);
|
||||||
|
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -835,7 +844,7 @@ int mcexec_wait_syscall(ihk_os_t os, struct syscall_wait_desc *__user req)
|
|||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
struct mcctrl_per_proc_data *ppd;
|
struct mcctrl_per_proc_data *ppd;
|
||||||
|
|
||||||
/* Look up per-process structure */
|
/* Get a reference to per-process structure */
|
||||||
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
||||||
|
|
||||||
if (unlikely(!ppd)) {
|
if (unlikely(!ppd)) {
|
||||||
@@ -848,7 +857,8 @@ int mcexec_wait_syscall(ihk_os_t os, struct syscall_wait_desc *__user req)
|
|||||||
if (packet) {
|
if (packet) {
|
||||||
printk("%s: ERROR: packet %p is already registered for thread %d\n",
|
printk("%s: ERROR: packet %p is already registered for thread %d\n",
|
||||||
__FUNCTION__, packet, task_pid_vnr(current));
|
__FUNCTION__, packet, task_pid_vnr(current));
|
||||||
return -EBUSY;
|
ret = -EBUSY;
|
||||||
|
goto put_ppd_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
@@ -874,12 +884,13 @@ retry_alloc:
|
|||||||
|
|
||||||
wqhln->task = current;
|
wqhln->task = current;
|
||||||
wqhln->req = 0;
|
wqhln->req = 0;
|
||||||
|
wqhln->packet = NULL;
|
||||||
init_waitqueue_head(&wqhln->wq_syscall);
|
init_waitqueue_head(&wqhln->wq_syscall);
|
||||||
|
|
||||||
/* Wait for a request.. */
|
|
||||||
list_add(&wqhln->list, &ppd->wq_list);
|
list_add(&wqhln->list, &ppd->wq_list);
|
||||||
ihk_ikc_spinlock_unlock(&ppd->wq_list_lock, irqflags);
|
ihk_ikc_spinlock_unlock(&ppd->wq_list_lock, irqflags);
|
||||||
|
|
||||||
|
/* Wait for a request.. */
|
||||||
ret = wait_event_interruptible(wqhln->wq_syscall, wqhln->req);
|
ret = wait_event_interruptible(wqhln->wq_syscall, wqhln->req);
|
||||||
|
|
||||||
/* Remove per-thread wait queue head */
|
/* Remove per-thread wait queue head */
|
||||||
@@ -891,7 +902,8 @@ retry_alloc:
|
|||||||
if (ret && !wqhln->req) {
|
if (ret && !wqhln->req) {
|
||||||
kfree(wqhln);
|
kfree(wqhln);
|
||||||
wqhln = NULL;
|
wqhln = NULL;
|
||||||
return -EINTR;
|
ret = -EINTR;
|
||||||
|
goto put_ppd_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = wqhln->packet;
|
packet = wqhln->packet;
|
||||||
@@ -927,7 +939,8 @@ retry_alloc:
|
|||||||
|
|
||||||
if (mcctrl_add_per_thread_data(ppd, current, packet) < 0) {
|
if (mcctrl_add_per_thread_data(ppd, current, packet) < 0) {
|
||||||
kprintf("%s: error adding per-thread data\n", __FUNCTION__);
|
kprintf("%s: error adding per-thread data\n", __FUNCTION__);
|
||||||
return -EINVAL;
|
ret = -EINVAL;;
|
||||||
|
goto put_ppd_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__do_in_kernel_syscall(os, packet)) {
|
if (__do_in_kernel_syscall(os, packet)) {
|
||||||
@@ -936,11 +949,13 @@ retry_alloc:
|
|||||||
|
|
||||||
if (mcctrl_delete_per_thread_data(ppd, current) < 0) {
|
if (mcctrl_delete_per_thread_data(ppd, current) < 0) {
|
||||||
kprintf("%s: error deleting per-thread data\n", __FUNCTION__);
|
kprintf("%s: error deleting per-thread data\n", __FUNCTION__);
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
return -EFAULT;
|
ret = -EINVAL;;
|
||||||
|
goto put_ppd_out;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
ret = 0;
|
||||||
|
goto put_ppd_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ihk_ikc_release_packet((struct ihk_ikc_free_packet *)packet,
|
ihk_ikc_release_packet((struct ihk_ikc_free_packet *)packet,
|
||||||
@@ -948,10 +963,15 @@ retry_alloc:
|
|||||||
|
|
||||||
if (mcctrl_delete_per_thread_data(ppd, current) < 0) {
|
if (mcctrl_delete_per_thread_data(ppd, current) < 0) {
|
||||||
kprintf("%s: error deleting per-thread data\n", __FUNCTION__);
|
kprintf("%s: error deleting per-thread data\n", __FUNCTION__);
|
||||||
return -EINVAL;
|
ret = -EINVAL;;
|
||||||
|
goto put_ppd_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
|
|
||||||
|
put_ppd_out:
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
long mcexec_pin_region(ihk_os_t os, unsigned long *__user arg)
|
long mcexec_pin_region(ihk_os_t os, unsigned long *__user arg)
|
||||||
@@ -1061,6 +1081,7 @@ long mcexec_ret_syscall(ihk_os_t os, struct syscall_ret_desc *__user arg)
|
|||||||
if (!packet) {
|
if (!packet) {
|
||||||
kprintf("%s: ERROR: no packet registered for TID %d\n",
|
kprintf("%s: ERROR: no packet registered for TID %d\n",
|
||||||
__FUNCTION__, task_pid_vnr(current));
|
__FUNCTION__, task_pid_vnr(current));
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1079,6 +1100,7 @@ long mcexec_ret_syscall(ihk_os_t os, struct syscall_ret_desc *__user arg)
|
|||||||
ret.size, NULL, 0);
|
ret.size, NULL, 0);
|
||||||
#endif
|
#endif
|
||||||
if (copy_from_user(rpm, (void *__user)ret.src, ret.size)) {
|
if (copy_from_user(rpm, (void *__user)ret.src, ret.size)) {
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1096,6 +1118,7 @@ long mcexec_ret_syscall(ihk_os_t os, struct syscall_ret_desc *__user arg)
|
|||||||
ihk_ikc_release_packet((struct ihk_ikc_free_packet *)packet,
|
ihk_ikc_release_packet((struct ihk_ikc_free_packet *)packet,
|
||||||
(usrdata->channels + packet->ref)->c);
|
(usrdata->channels + packet->ref)->c);
|
||||||
|
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1164,7 +1187,7 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (os_ind < 0) {
|
if (os_ind < 0) {
|
||||||
return EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
||||||
@@ -1176,6 +1199,7 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ppd->ud = usrdata;
|
||||||
ppd->pid = task_tgid_vnr(current);
|
ppd->pid = task_tgid_vnr(current);
|
||||||
/*
|
/*
|
||||||
* XXX: rpgtable will be updated in __do_in_kernel_syscall()
|
* XXX: rpgtable will be updated in __do_in_kernel_syscall()
|
||||||
@@ -1188,6 +1212,8 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
|
|||||||
spin_lock_init(&ppd->wq_list_lock);
|
spin_lock_init(&ppd->wq_list_lock);
|
||||||
memset(&ppd->cpu_set, 0, sizeof(cpumask_t));
|
memset(&ppd->cpu_set, 0, sizeof(cpumask_t));
|
||||||
ppd->ikc_target_cpu = 0;
|
ppd->ikc_target_cpu = 0;
|
||||||
|
/* Final ref will be dropped in close_exec() */
|
||||||
|
atomic_set(&ppd->refcount, 1);
|
||||||
|
|
||||||
for (i = 0; i < MCCTRL_PER_THREAD_DATA_HASH_SIZE; ++i) {
|
for (i = 0; i < MCCTRL_PER_THREAD_DATA_HASH_SIZE; ++i) {
|
||||||
INIT_LIST_HEAD(&ppd->per_thread_data_hash[i]);
|
INIT_LIST_HEAD(&ppd->per_thread_data_hash[i]);
|
||||||
@@ -1196,36 +1222,33 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
|
|||||||
|
|
||||||
if (mcctrl_add_per_proc_data(usrdata, ppd->pid, ppd) < 0) {
|
if (mcctrl_add_per_proc_data(usrdata, ppd->pid, ppd) < 0) {
|
||||||
printk("%s: error adding per process data\n", __FUNCTION__);
|
printk("%s: error adding per process data\n", __FUNCTION__);
|
||||||
retval = EINVAL;
|
retval = -EINVAL;
|
||||||
goto out_free_ppd;
|
kfree(ppd);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/* Only deallocate in case of an error if we added it above */
|
|
||||||
ppd = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY);
|
pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY);
|
||||||
if (!pathbuf) {
|
if (!pathbuf) {
|
||||||
retval = ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto out_error_drop_ppd;
|
goto out_put_ppd;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = open_exec(filename);
|
file = open_exec(filename);
|
||||||
retval = PTR_ERR(file);
|
retval = PTR_ERR(file);
|
||||||
if (IS_ERR(file)) {
|
if (IS_ERR(file)) {
|
||||||
goto out_error_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullpath = d_path(&file->f_path, pathbuf, PATH_MAX);
|
fullpath = d_path(&file->f_path, pathbuf, PATH_MAX);
|
||||||
if (IS_ERR(fullpath)) {
|
if (IS_ERR(fullpath)) {
|
||||||
retval = PTR_ERR(fullpath);
|
retval = PTR_ERR(fullpath);
|
||||||
goto out_error_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
mcef = kmalloc(sizeof(*mcef), GFP_KERNEL);
|
mcef = kmalloc(sizeof(*mcef), GFP_KERNEL);
|
||||||
if (!mcef) {
|
if (!mcef) {
|
||||||
retval = ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto out_put_file;
|
goto out_put_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1260,13 +1283,12 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
|
|||||||
|
|
||||||
out_put_file:
|
out_put_file:
|
||||||
fput(file);
|
fput(file);
|
||||||
out_error_free:
|
out_free:
|
||||||
kfree(pathbuf);
|
kfree(pathbuf);
|
||||||
out_error_drop_ppd:
|
out_put_ppd:
|
||||||
if (ppd) mcctrl_delete_per_proc_data(usrdata, ppd->pid);
|
mcctrl_put_per_proc_data(ppd);
|
||||||
out_free_ppd:
|
out:
|
||||||
if (ppd) kfree(ppd);
|
return retval;
|
||||||
return -retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1281,12 +1303,12 @@ int mcexec_close_exec(ihk_os_t os)
|
|||||||
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
||||||
|
|
||||||
if (ppd) {
|
if (ppd) {
|
||||||
mcctrl_delete_per_proc_data(usrdata, ppd->pid);
|
/* One for the reference and one for deallocation */
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
|
|
||||||
dprintk("pid: %d, tid: %d: rpgtable for %d (0x%lx) removed\n",
|
dprintk("pid: %d, tid: %d: rpgtable for %d (0x%lx) removed\n",
|
||||||
task_tgid_vnr(current), current->pid, ppd->pid, ppd->rpgtable);
|
task_tgid_vnr(current), current->pid, ppd->pid, ppd->rpgtable);
|
||||||
|
|
||||||
kfree(ppd);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printk("WARNING: no per process data for pid %d ?\n",
|
printk("WARNING: no per process data for pid %d ?\n",
|
||||||
@@ -1550,5 +1572,6 @@ void mcexec_prepare_ack(ihk_os_t os, unsigned long arg, int err)
|
|||||||
desc->status = 1;
|
desc->status = 1;
|
||||||
|
|
||||||
wake_up_all(&ppd->wq_prepare);
|
wake_up_all(&ppd->wq_prepare);
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ struct mcctrl_per_thread_data {
|
|||||||
#define MCCTRL_PER_THREAD_DATA_HASH_MASK (MCCTRL_PER_THREAD_DATA_HASH_SIZE - 1)
|
#define MCCTRL_PER_THREAD_DATA_HASH_MASK (MCCTRL_PER_THREAD_DATA_HASH_SIZE - 1)
|
||||||
|
|
||||||
struct mcctrl_per_proc_data {
|
struct mcctrl_per_proc_data {
|
||||||
|
struct mcctrl_usrdata *ud;
|
||||||
struct list_head hash;
|
struct list_head hash;
|
||||||
int pid;
|
int pid;
|
||||||
unsigned long rpgtable; /* per process, not per OS */
|
unsigned long rpgtable; /* per process, not per OS */
|
||||||
@@ -201,6 +202,7 @@ struct mcctrl_per_proc_data {
|
|||||||
rwlock_t per_thread_data_hash_lock[MCCTRL_PER_THREAD_DATA_HASH_SIZE];
|
rwlock_t per_thread_data_hash_lock[MCCTRL_PER_THREAD_DATA_HASH_SIZE];
|
||||||
cpumask_t cpu_set;
|
cpumask_t cpu_set;
|
||||||
int ikc_target_cpu;
|
int ikc_target_cpu;
|
||||||
|
atomic_t refcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfsm_req {
|
struct sysfsm_req {
|
||||||
@@ -315,8 +317,9 @@ int __do_in_kernel_syscall(ihk_os_t os, struct ikc_scd_packet *packet);
|
|||||||
int mcctrl_add_per_proc_data(struct mcctrl_usrdata *ud, int pid,
|
int mcctrl_add_per_proc_data(struct mcctrl_usrdata *ud, int pid,
|
||||||
struct mcctrl_per_proc_data *ppd);
|
struct mcctrl_per_proc_data *ppd);
|
||||||
int mcctrl_delete_per_proc_data(struct mcctrl_usrdata *ud, int pid);
|
int mcctrl_delete_per_proc_data(struct mcctrl_usrdata *ud, int pid);
|
||||||
inline struct mcctrl_per_proc_data *mcctrl_get_per_proc_data(
|
struct mcctrl_per_proc_data *mcctrl_get_per_proc_data(
|
||||||
struct mcctrl_usrdata *ud, int pid);
|
struct mcctrl_usrdata *ud, int pid);
|
||||||
|
void mcctrl_put_per_proc_data(struct mcctrl_per_proc_data *ppd);
|
||||||
|
|
||||||
int mcctrl_add_per_thread_data(struct mcctrl_per_proc_data* ppd,
|
int mcctrl_add_per_thread_data(struct mcctrl_per_proc_data* ppd,
|
||||||
struct task_struct *task, void *data);
|
struct task_struct *task, void *data);
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ static int remote_page_fault(struct mcctrl_usrdata *usrdata, void *fault_addr, u
|
|||||||
error = -ENOENT;
|
error = -ENOENT;
|
||||||
printk("%s: no packet registered for TID %d\n",
|
printk("%s: no packet registered for TID %d\n",
|
||||||
__FUNCTION__, task_pid_vnr(current));
|
__FUNCTION__, task_pid_vnr(current));
|
||||||
goto out_no_unmap;
|
goto out_put_ppd;
|
||||||
}
|
}
|
||||||
|
|
||||||
req = &packet->req;
|
req = &packet->req;
|
||||||
@@ -434,9 +434,11 @@ out:
|
|||||||
ihk_device_unmap_virtual(ihk_os_to_dev(usrdata->os), resp, sizeof(*resp));
|
ihk_device_unmap_virtual(ihk_os_to_dev(usrdata->os), resp, sizeof(*resp));
|
||||||
ihk_device_unmap_memory(ihk_os_to_dev(usrdata->os), phys, sizeof(*resp));
|
ihk_device_unmap_memory(ihk_os_to_dev(usrdata->os), phys, sizeof(*resp));
|
||||||
|
|
||||||
out_no_unmap:
|
out_put_ppd:
|
||||||
dprintk("%s: tid: %d, fault_addr: %lu, reason: %lu, error: %d\n",
|
dprintk("%s: tid: %d, fault_addr: %lu, reason: %lu, error: %d\n",
|
||||||
__FUNCTION__, task_pid_vnr(current), fault_addr, reason, error);
|
__FUNCTION__, task_pid_vnr(current), fault_addr, reason, error);
|
||||||
|
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,6 +576,7 @@ static int rus_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||||||
size_t pix;
|
size_t pix;
|
||||||
#endif
|
#endif
|
||||||
struct mcctrl_per_proc_data *ppd;
|
struct mcctrl_per_proc_data *ppd;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
dprintk("mcctrl:page fault:flags %#x pgoff %#lx va %p page %p\n",
|
dprintk("mcctrl:page fault:flags %#x pgoff %#lx va %p page %p\n",
|
||||||
vmf->flags, vmf->pgoff, vmf->virtual_address, vmf->page);
|
vmf->flags, vmf->pgoff, vmf->virtual_address, vmf->page);
|
||||||
@@ -584,7 +587,6 @@ static int rus_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||||||
ppd = mcctrl_get_per_proc_data(usrdata, vma->vm_mm->owner->pid);
|
ppd = mcctrl_get_per_proc_data(usrdata, vma->vm_mm->owner->pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!ppd) {
|
if (!ppd) {
|
||||||
kprintf("%s: ERROR: no per-process structure for PID %d??\n",
|
kprintf("%s: ERROR: no per-process structure for PID %d??\n",
|
||||||
__FUNCTION__, task_tgid_vnr(current));
|
__FUNCTION__, task_tgid_vnr(current));
|
||||||
@@ -618,7 +620,8 @@ static int rus_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||||||
if (error) {
|
if (error) {
|
||||||
printk("mcctrl:page fault error:flags %#x pgoff %#lx va %p page %p\n",
|
printk("mcctrl:page fault error:flags %#x pgoff %#lx va %p page %p\n",
|
||||||
vmf->flags, vmf->pgoff, vmf->virtual_address, vmf->page);
|
vmf->flags, vmf->pgoff, vmf->virtual_address, vmf->page);
|
||||||
return VM_FAULT_SIGBUS;
|
ret = VM_FAULT_SIGBUS;
|
||||||
|
goto put_and_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rva = (unsigned long)vmf->virtual_address & ~(pgsize - 1);
|
rva = (unsigned long)vmf->virtual_address & ~(pgsize - 1);
|
||||||
@@ -655,10 +658,15 @@ static int rus_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||||||
if (error) {
|
if (error) {
|
||||||
printk("mcctrl:page fault:remap error:flags %#x pgoff %#lx va %p page %p\n",
|
printk("mcctrl:page fault:remap error:flags %#x pgoff %#lx va %p page %p\n",
|
||||||
vmf->flags, vmf->pgoff, vmf->virtual_address, vmf->page);
|
vmf->flags, vmf->pgoff, vmf->virtual_address, vmf->page);
|
||||||
return VM_FAULT_SIGBUS;
|
ret = VM_FAULT_SIGBUS;
|
||||||
|
goto put_and_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return VM_FAULT_NOPAGE;
|
ret = VM_FAULT_NOPAGE;
|
||||||
|
|
||||||
|
put_and_out:
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vm_operations_struct rus_vmops = {
|
static struct vm_operations_struct rus_vmops = {
|
||||||
@@ -1623,6 +1631,7 @@ int __do_in_kernel_syscall(ihk_os_t os, struct ikc_scd_packet *packet)
|
|||||||
|
|
||||||
dprintk("%s: pid: %d, rpgtable: 0x%lx updated\n",
|
dprintk("%s: pid: %d, rpgtable: 0x%lx updated\n",
|
||||||
__FUNCTION__, ppd->pid, ppd->rpgtable);
|
__FUNCTION__, ppd->pid, ppd->rpgtable);
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = clear_pte_range(sc->args[0], sc->args[1]);
|
ret = clear_pte_range(sc->args[0], sc->args[1]);
|
||||||
|
|||||||
Reference in New Issue
Block a user