diff --git a/executer/kernel/mcctrl/arch/arm64/archdeps.c b/executer/kernel/mcctrl/arch/arm64/archdeps.c index 087171ab..2d9a7003 100644 --- a/executer/kernel/mcctrl/arch/arm64/archdeps.c +++ b/executer/kernel/mcctrl/arch/arm64/archdeps.c @@ -2,6 +2,7 @@ #include #include #include +#include #if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE #include #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */ @@ -27,6 +28,14 @@ void *vdso_end; static struct vm_special_mapping (*vdso_spec)[2]; #endif +/* Tofu CQ and barrier gate release functions */ +struct file_operations *mcctrl_tof_utofu_procfs_ops_cq; +int (*mcctrl_tof_utofu_release_cq)(struct inode *inode, + struct file *filp); +struct file_operations *mcctrl_tof_utofu_procfs_ops_bch; +int (*mcctrl_tof_utofu_release_bch)(struct inode *inode, + struct file *filp); + int arch_symbols_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) @@ -43,6 +52,26 @@ int arch_symbols_init(void) return -EFAULT; #endif + mcctrl_tof_utofu_procfs_ops_cq = + (void *)kallsyms_lookup_name("tof_utofu_procfs_ops_cq"); + if (WARN_ON(!mcctrl_tof_utofu_procfs_ops_cq)) + return -EFAULT; + + mcctrl_tof_utofu_procfs_ops_bch = + (void *)kallsyms_lookup_name("tof_utofu_procfs_ops_bch"); + if (WARN_ON(!mcctrl_tof_utofu_procfs_ops_bch)) + return -EFAULT; + + mcctrl_tof_utofu_release_cq = + (void *)kallsyms_lookup_name("tof_utofu_release_cq"); + if (WARN_ON(!mcctrl_tof_utofu_release_cq)) + return -EFAULT; + + mcctrl_tof_utofu_release_bch = + (void *)kallsyms_lookup_name("tof_utofu_release_bch"); + if (WARN_ON(!mcctrl_tof_utofu_release_bch)) + return -EFAULT; + return 0; } @@ -417,3 +446,106 @@ long arch_switch_ctx(struct uti_switch_ctx_desc *desc) out: return rc; } + + +/* + * Tofu CQ and BCH release handlers + */ +int __mcctrl_tof_utofu_release_cq(struct inode *inode, struct file *filp); +int __mcctrl_tof_utofu_release_bch(struct inode *inode, struct file *filp); + +void mcctrl_tofu_hijack_release_handlers(void) +{ + mcctrl_tof_utofu_procfs_ops_cq->release = + __mcctrl_tof_utofu_release_cq; + mcctrl_tof_utofu_procfs_ops_bch->release = + __mcctrl_tof_utofu_release_bch; +} + +void mcctrl_tofu_restore_release_handlers(void) +{ + mcctrl_tof_utofu_procfs_ops_cq->release = + mcctrl_tof_utofu_release_cq; + mcctrl_tof_utofu_procfs_ops_bch->release = + mcctrl_tof_utofu_release_bch; +} + +int __mcctrl_tof_utofu_release_handler(struct inode *inode, struct file *filp, + int (*__release_func)(struct inode *inode, struct file *filp)) +{ + struct mcctrl_usrdata *usrdata; + struct mcctrl_file_to_pidfd *f2pfd; + struct mcctrl_per_proc_data *ppd; + struct ikc_scd_packet isp; + int ret; + + dprintk("%s: current PID: %d, comm: %s \n", + __func__, task_tgid_vnr(current), current->comm); + + f2pfd = mcctrl_file_to_pidfd_hash_lookup(filp, current->group_leader); + if (!f2pfd) { + goto out; + } + + dprintk("%s: current PID: %d, PID: %d, fd: %d ...\n", + __func__, task_tgid_vnr(current), f2pfd->pid, f2pfd->fd); + usrdata = ihk_host_os_get_usrdata(f2pfd->os); + + /* Look up per-process structure */ + ppd = mcctrl_get_per_proc_data(usrdata, f2pfd->pid); + if (!ppd) { + pr_err("%s: PID: %d, fd: %d no PPD\n", + __func__, f2pfd->pid, f2pfd->fd); + goto out; + } + + dprintk("%s: PID: %d, fd: %d PPD OK\n", + __func__, f2pfd->pid, f2pfd->fd); + + /* + * We are in release() due to the process being killed, + * or because the application didn't close the file properly. + * Ask McKernel to clean up this fd. + */ + isp.msg = SCD_MSG_CLEANUP_FD; + isp.pid = f2pfd->pid; + isp.arg = f2pfd->fd; + + ret = mcctrl_ikc_send_wait(f2pfd->os, ppd->ikc_target_cpu, + &isp, -20, NULL, NULL, 0); + if (ret != 0) { + dprintk("%s: WARNING: failed to send IKC msg: %d\n", + __func__, ret); + } + + mcctrl_file_to_pidfd_hash_remove(filp, f2pfd->os, + current->group_leader, f2pfd->fd); + + mcctrl_put_per_proc_data(ppd); + + /* Do not call into Linux driver if timed out in SIGKILL.. */ + if (ret == -ETIME && __fatal_signal_pending(current)) { + pr_err("%s: WARNING: failed to send IKC msg in SIGKILL: %d\n", + __func__, ret); + goto out_no_release; + } +out: + dprintk("%s: current PID: %d, comm: %s -> calling release\n", + __func__, task_tgid_vnr(current), current->comm); + return __release_func(inode, filp); + +out_no_release: + return ret; +} + +int __mcctrl_tof_utofu_release_cq(struct inode *inode, struct file *filp) +{ + return __mcctrl_tof_utofu_release_handler(inode, filp, + mcctrl_tof_utofu_release_cq); +} + +int __mcctrl_tof_utofu_release_bch(struct inode *inode, struct file *filp) +{ + return __mcctrl_tof_utofu_release_handler(inode, filp, + mcctrl_tof_utofu_release_bch); +} diff --git a/executer/kernel/mcctrl/control.c b/executer/kernel/mcctrl/control.c index b90aaa68..99b51a13 100644 --- a/executer/kernel/mcctrl/control.c +++ b/executer/kernel/mcctrl/control.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -378,6 +379,7 @@ static void release_handler(ihk_os_t os, void *param) int os_ind = ihk_host_os_get_index(os); unsigned long flags; struct host_thread *thread; + int ret; /* Finalize FS switch for uti threads */ write_lock_irqsave(&host_thread_lock, flags); @@ -399,7 +401,13 @@ static void release_handler(ihk_os_t os, void *param) dprintk("%s: SCD_MSG_CLEANUP_PROCESS, info: %p, cpu: %d\n", __FUNCTION__, info, info->cpu); - mcctrl_ikc_send(os, info->cpu, &isp); + ret = mcctrl_ikc_send_wait(os, info->cpu, + &isp, -20, NULL, NULL, 0); + if (ret != 0) { + printk("%s: WARNING: failed to send IKC msg: %d\n", + __func__, ret); + } + if (os_ind >= 0) { delete_pid_entry(os_ind, info->pid); } diff --git a/executer/kernel/mcctrl/driver.c b/executer/kernel/mcctrl/driver.c index 3db7a485..39afb7c2 100644 --- a/executer/kernel/mcctrl/driver.c +++ b/executer/kernel/mcctrl/driver.c @@ -50,6 +50,7 @@ extern void procfs_exit(int); extern void uti_attr_finalize(void); extern void binfmt_mcexec_init(void); extern void binfmt_mcexec_exit(void); +extern void mcctrl_file_to_pidfd_hash_init(void); extern int mcctrl_os_read_cpu_register(ihk_os_t os, int cpu, struct ihk_os_cpu_register *desc); @@ -57,6 +58,11 @@ extern int mcctrl_os_write_cpu_register(ihk_os_t os, int cpu, struct ihk_os_cpu_register *desc); extern int mcctrl_get_request_os_cpu(ihk_os_t os, int *cpu); +#ifdef ENABLE_TOFU +extern void mcctrl_tofu_hijack_release_handlers(void); +extern void mcctrl_tofu_restore_release_handlers(void); +#endif + static long mcctrl_ioctl(ihk_os_t os, unsigned int request, void *priv, unsigned long arg, struct file *file) { @@ -319,10 +325,15 @@ static int __init mcctrl_init(void) } binfmt_mcexec_init(); + mcctrl_file_to_pidfd_hash_init(); if ((ret = symbols_init())) goto error; +#ifdef ENABLE_TOFU + mcctrl_tofu_hijack_release_handlers(); +#endif + if ((ret = ihk_host_register_os_notifier(&mcctrl_os_notifier)) != 0) { printk("mcctrl: error: registering OS notifier\n"); goto error; @@ -345,6 +356,9 @@ static void __exit mcctrl_exit(void) binfmt_mcexec_exit(); uti_attr_finalize(); +#ifdef ENABLE_TOFU + mcctrl_tofu_restore_release_handlers(); +#endif printk("mcctrl: unregistered.\n"); } diff --git a/executer/kernel/mcctrl/ikc.c b/executer/kernel/mcctrl/ikc.c index e483c70c..8ceab1f0 100644 --- a/executer/kernel/mcctrl/ikc.c +++ b/executer/kernel/mcctrl/ikc.c @@ -148,8 +148,29 @@ int mcctrl_ikc_send_wait(ihk_os_t os, int cpu, struct ikc_scd_packet *pisp, } if (timeout) { - ret = wait_event_interruptible_timeout(desc->wq, - desc->status, timeout); + /* + * Negative timeout indicates busy waiting, which can be used + * in situations where wait_event_interruptible_XXX() would + * fail, e.g., in a signal handler, at the time the process + * is being killed, etc. + */ + if (timeout < 0) { + unsigned long timeout_jiffies = + jiffies + msecs_to_jiffies(timeout * -1); + ret = -ETIME; + + while (time_before(jiffies, timeout_jiffies)) { + schedule(); + if (READ_ONCE(desc->status)) { + ret = 0; + break; + } + } + } + else { + ret = wait_event_interruptible_timeout(desc->wq, + desc->status, msecs_to_jiffies(timeout)); + } } else { ret = wait_event_interruptible(desc->wq, desc->status); } @@ -211,6 +232,8 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, case SCD_MSG_PROCFS_ANSWER: case SCD_MSG_REMOTE_PAGE_FAULT_ANSWER: case SCD_MSG_CPU_RW_REG_RESP: + case SCD_MSG_CLEANUP_PROCESS_RESP: + case SCD_MSG_CLEANUP_FD_RESP: mcctrl_wakeup_cb(__os, pisp); break; diff --git a/executer/kernel/mcctrl/mcctrl.h b/executer/kernel/mcctrl/mcctrl.h index 606a4a0f..ed9daa8c 100644 --- a/executer/kernel/mcctrl/mcctrl.h +++ b/executer/kernel/mcctrl/mcctrl.h @@ -58,7 +58,8 @@ #define SCD_MSG_SEND_SIGNAL 0x7 #define SCD_MSG_SEND_SIGNAL_ACK 0x8 #define SCD_MSG_CLEANUP_PROCESS 0x9 -#define SCD_MSG_GET_VDSO_INFO 0xa +#define SCD_MSG_CLEANUP_PROCESS_RESP 0xa +#define SCD_MSG_GET_VDSO_INFO 0xb //#define SCD_MSG_GET_CPU_MAPPING 0xc //#define SCD_MSG_REPLY_GET_CPU_MAPPING 0xd @@ -104,6 +105,8 @@ #define SCD_MSG_CPU_RW_REG 0x52 #define SCD_MSG_CPU_RW_REG_RESP 0x53 +#define SCD_MSG_CLEANUP_FD 0x54 +#define SCD_MSG_CLEANUP_FD_RESP 0x55 #define SCD_MSG_FUTEX_WAKE 0x60 @@ -556,4 +559,29 @@ struct uti_futex_resp { int done; wait_queue_head_t wq; }; + +/* + * Hash table to keep track of files and related processes + * and file descriptors. + * NOTE: Used for Tofu driver release handlers. + */ +#define MCCTRL_FILE_2_PIDFD_HASH_SHIFT 4 +#define MCCTRL_FILE_2_PIDFD_HASH_SIZE (1 << MCCTRL_FILE_2_PIDFD_HASH_SHIFT) +#define MCCTRL_FILE_2_PIDFD_HASH_MASK (MCCTRL_FILE_2_PIDFD_HASH_SIZE - 1) + +struct mcctrl_file_to_pidfd { + struct file *filp; + ihk_os_t os; + struct task_struct *group_leader; + int pid; + int fd; + struct list_head hash; +}; + +int mcctrl_file_to_pidfd_hash_insert(struct file *filp, + ihk_os_t os, int pid, struct task_struct *group_leader, int fd); +struct mcctrl_file_to_pidfd *mcctrl_file_to_pidfd_hash_lookup( + struct file *filp, struct task_struct *group_leader); +int mcctrl_file_to_pidfd_hash_remove(struct file *filp, + ihk_os_t os, struct task_struct *group_leader, int fd); #endif diff --git a/executer/kernel/mcctrl/syscall.c b/executer/kernel/mcctrl/syscall.c index be7bee39..3fc69980 100644 --- a/executer/kernel/mcctrl/syscall.c +++ b/executer/kernel/mcctrl/syscall.c @@ -1843,6 +1843,136 @@ static long pager_call(ihk_os_t os, struct syscall_request *req) return ret; } +struct list_head mcctrl_file_to_pidfd_hash[MCCTRL_FILE_2_PIDFD_HASH_SIZE]; +spinlock_t mcctrl_file_to_pidfd_hash_lock; + +void mcctrl_file_to_pidfd_hash_init(void) +{ + int hash; + spin_lock_init(&mcctrl_file_to_pidfd_hash_lock); + + for (hash = 0; hash < MCCTRL_FILE_2_PIDFD_HASH_SIZE; ++hash) { + INIT_LIST_HEAD(&mcctrl_file_to_pidfd_hash[hash]); + } +} + +int mcctrl_file_to_pidfd_hash_insert(struct file *filp, + ihk_os_t os, int pid, struct task_struct *group_leader, int fd) +{ + unsigned long irqflags; + struct mcctrl_file_to_pidfd *file2pidfd_iter; + struct mcctrl_file_to_pidfd *file2pidfd; + int hash = (int)((unsigned long)filp & + (unsigned long)MCCTRL_FILE_2_PIDFD_HASH_MASK); + int ret = 0; + + file2pidfd = kmalloc(sizeof(*file2pidfd), GFP_ATOMIC); + if (!file2pidfd) + return -ENOMEM; + + file2pidfd->filp = filp; + file2pidfd->os = os; + file2pidfd->pid = pid; + file2pidfd->group_leader = group_leader; + file2pidfd->fd = fd; + + spin_lock_irqsave(&mcctrl_file_to_pidfd_hash_lock, irqflags); + list_for_each_entry(file2pidfd_iter, + &mcctrl_file_to_pidfd_hash[hash], hash) { + if (file2pidfd_iter->filp == filp) { + printk("%s: WARNING: filp: %p, pid: %d, fd: %d exists\n", + __func__, filp, pid, fd); + ret = -EBUSY; + goto free_out; + } + } + + list_add_tail(&file2pidfd->hash, + &mcctrl_file_to_pidfd_hash[hash]); + dprintk("%s: filp: %p, pid: %d, fd: %d added\n", + __func__, filp, pid, fd); + + spin_unlock_irqrestore(&mcctrl_file_to_pidfd_hash_lock, irqflags); + return ret; + +free_out: + kfree(file2pidfd); + spin_unlock_irqrestore(&mcctrl_file_to_pidfd_hash_lock, irqflags); + return ret; +} + +/* + * XXX: lookup relies on group_leader to identify the process + * because PIDs might be different across name spaces (e.g., + * when using Docker) + */ +struct mcctrl_file_to_pidfd *mcctrl_file_to_pidfd_hash_lookup( + struct file *filp, struct task_struct *group_leader) +{ + unsigned long irqflags; + struct mcctrl_file_to_pidfd *file2pidfd_iter; + struct mcctrl_file_to_pidfd *file2pidfd = NULL; + int hash = (int)((unsigned long)filp & + (unsigned long)MCCTRL_FILE_2_PIDFD_HASH_MASK); + + spin_lock_irqsave(&mcctrl_file_to_pidfd_hash_lock, irqflags); + list_for_each_entry(file2pidfd_iter, + &mcctrl_file_to_pidfd_hash[hash], hash) { + if (file2pidfd_iter->filp == filp && + file2pidfd_iter->group_leader == group_leader) { + file2pidfd = file2pidfd_iter; + dprintk("%s: filp: %p, pid: %d, fd: %d found\n", + __func__, filp, file2pidfd->pid, file2pidfd->fd); + break; + } + } + + spin_unlock_irqrestore(&mcctrl_file_to_pidfd_hash_lock, irqflags); + + return file2pidfd; +} + +int mcctrl_file_to_pidfd_hash_remove(struct file *filp, + ihk_os_t os, struct task_struct *group_leader, int fd) +{ + unsigned long irqflags; + struct mcctrl_file_to_pidfd *file2pidfd_iter; + int hash = (int)((unsigned long)filp & + (unsigned long)MCCTRL_FILE_2_PIDFD_HASH_MASK); + int ret = 0; + + spin_lock_irqsave(&mcctrl_file_to_pidfd_hash_lock, irqflags); + list_for_each_entry(file2pidfd_iter, + &mcctrl_file_to_pidfd_hash[hash], hash) { + if (file2pidfd_iter->filp != filp) + continue; + + if (file2pidfd_iter->os != os) + continue; + + if (file2pidfd_iter->group_leader != group_leader) + continue; + + if (file2pidfd_iter->fd != fd) + continue; + + list_del(&file2pidfd_iter->hash); + dprintk("%s: filp: %p, pid: %d, fd: %d removed\n", + __func__, filp, file2pidfd_iter->pid, fd); + kfree(file2pidfd_iter); + goto unlock_out; + } + + dprintk("%s: filp: %p, pid: %d, fd: %d couldn't be found\n", + __func__, filp, pid, fd); + ret = -ENOENT; + +unlock_out: + spin_unlock_irqrestore(&mcctrl_file_to_pidfd_hash_lock, irqflags); + return ret; +} + + void __return_syscall(ihk_os_t os, struct ikc_scd_packet *packet, long ret, int stid) { @@ -1874,18 +2004,14 @@ void __return_syscall(ihk_os_t os, struct ikc_scd_packet *packet, res->stid = stid; #ifdef ENABLE_TOFU - /* Record PDE_DATA after open()/ioctl() calls for Tofu driver */ - if ((packet->req.number == __NR_ioctl && ret == 0) || - (packet->req.number == __NR_openat && ret > 1)) { + /* Record PDE_DATA after open() calls for Tofu driver */ + if (packet->req.number == __NR_openat && ret > 1) { char *pathbuf, *fullpath; struct fd f; + int fd; - if (packet->req.number == __NR_ioctl) { - f = fdget(packet->req.args[0]); - } - else if (packet->req.number == __NR_openat) { - f = fdget(ret); - } + fd = ret; + f = fdget(fd); if (!f.file) { goto out_notify; @@ -1903,12 +2029,11 @@ void __return_syscall(ihk_os_t os, struct ikc_scd_packet *packet, if (!strncmp("/proc/tofu/dev/", fullpath, 15)) { res->pde_data = PDE_DATA(file_inode(f.file)); - dprintk("%s: %s(): fd: %ld, path: %s, PDE_DATA: 0x%lx\n", - __func__, - packet->req.number == __NR_ioctl ? "ioctl" : "openat", - packet->req.args[0], - fullpath, - (unsigned long)res->pde_data); + dprintk("%s: fd: %d, path: %s, PDE_DATA: 0x%lx\n", + __func__, + fd, + fullpath, + (unsigned long)res->pde_data); dprintk("%s: pgd_index: %ld, pmd_index: %ld, pte_index: %ld\n", __func__, pgd_index((unsigned long)res->pde_data), @@ -1918,6 +2043,9 @@ void __return_syscall(ihk_os_t os, struct ikc_scd_packet *packet, dprintk("CONFIG_ARM64_VA_BITS: %d, PGDIR_SHIFT: %d\n", CONFIG_ARM64_VA_BITS, PGDIR_SHIFT); #endif + mcctrl_file_to_pidfd_hash_insert(f.file, os, + task_tgid_vnr(current), + current->group_leader, fd); } out_free: @@ -2330,6 +2458,26 @@ int __do_in_kernel_syscall(ihk_os_t os, struct ikc_scd_packet *packet) dprintk("%s: system call: %lx\n", __FUNCTION__, sc->args[0]); switch (sc->number) { + case __NR_close: { + struct fd f; + int fd; + + fd = (int)sc->args[0]; + if (fd > 2) { + f = fdget(fd); + + if (f.file) { + mcctrl_file_to_pidfd_hash_remove(f.file, os, + current->group_leader, fd); + fdput(f); + } + } + + error = -ENOSYS; + goto out; + + break; + } case __NR_mmap: ret = pager_call(os, sc); break; diff --git a/kernel/host.c b/kernel/host.c index 801adafa..6718b8be 100644 --- a/kernel/host.c +++ b/kernel/host.c @@ -778,12 +778,36 @@ out_remote_pf: ret = 0; break; - case SCD_MSG_CLEANUP_PROCESS: + case SCD_MSG_CLEANUP_PROCESS: { + extern int process_cleanup_before_terminate(int pid); dkprintf("SCD_MSG_CLEANUP_PROCESS pid=%d, thread=0x%llx\n", packet->pid, packet->arg); + + pckt.msg = SCD_MSG_CLEANUP_PROCESS_RESP; + pckt.err = process_cleanup_before_terminate(packet->pid); + pckt.ref = packet->ref; + pckt.arg = packet->arg; + pckt.reply = packet->reply; + syscall_channel_send(resp_channel, &pckt); terminate_host(packet->pid, (struct thread *)packet->arg); ret = 0; break; + } + + case SCD_MSG_CLEANUP_FD: { + extern int process_cleanup_fd(int pid, int fd); + pckt.msg = SCD_MSG_CLEANUP_FD_RESP; + pckt.err = process_cleanup_fd(packet->pid, packet->arg); + dkprintf("SCD_MSG_CLEANUP_FD pid=%d, fd=%d -> err: %d\n", + packet->pid, packet->arg, pckt.err); + + pckt.ref = packet->ref; + pckt.arg = packet->arg; + pckt.reply = packet->reply; + syscall_channel_send(resp_channel, &pckt); + ret = 0; + break; + } case SCD_MSG_DEBUG_LOG: dkprintf("SCD_MSG_DEBUG_LOG code=%lx\n", packet->arg); diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 89071e0f..2505a64e 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -39,7 +39,8 @@ #define SCD_MSG_SEND_SIGNAL 0x7 #define SCD_MSG_SEND_SIGNAL_ACK 0x8 #define SCD_MSG_CLEANUP_PROCESS 0x9 -#define SCD_MSG_GET_VDSO_INFO 0xa +#define SCD_MSG_CLEANUP_PROCESS_RESP 0xa +#define SCD_MSG_GET_VDSO_INFO 0xb #define SCD_MSG_GET_CPU_MAPPING 0xc #define SCD_MSG_REPLY_GET_CPU_MAPPING 0xd @@ -84,6 +85,8 @@ #define SCD_MSG_CPU_RW_REG 0x52 #define SCD_MSG_CPU_RW_REG_RESP 0x53 +#define SCD_MSG_CLEANUP_FD 0x54 +#define SCD_MSG_CLEANUP_FD_RESP 0x55 #define SCD_MSG_FUTEX_WAKE 0x60 diff --git a/kernel/syscall.c b/kernel/syscall.c index 92422e6b..eac055ff 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1303,10 +1303,8 @@ void terminate(int rc, int sig) if (proc->enable_tofu && proc->fd_pde_data[fd]) { extern void tof_utofu_release_fd(struct process *proc, int fd); - if (proc->fd_path[fd]) { - dkprintf("%s: -> tof_utofu_release_fd() @ fd: %d (%s)\n", - __func__, fd, proc->fd_path[fd]); - } + dkprintf("%s: -> tof_utofu_release_fd() @ fd: %d (%s)\n", + __func__, fd, proc->fd_path[fd]); tof_utofu_release_fd(proc, fd); proc->fd_pde_data[fd] = NULL; } @@ -1487,6 +1485,67 @@ void terminate(int rc, int sig) panic("panic"); } +int __process_cleanup_fd(struct process *proc, int fd) +{ +#ifdef ENABLE_TOFU + /* Tofu? */ + if (proc->enable_tofu) { + extern void tof_utofu_release_fd(struct process *proc, int fd); + + dkprintf("%s: -> tof_utofu_release_fd() @ fd: %d (%s)\n", + __func__, fd, proc->fd_path[fd]); + tof_utofu_release_fd(proc, fd); + proc->fd_pde_data[fd] = NULL; + + if (proc->fd_path[fd]) { + kfree(proc->fd_path[fd]); + proc->fd_path[fd] = NULL; + } + } +#endif + return 0; +} + +int process_cleanup_fd(int pid, int fd) +{ + struct process *proc; + struct mcs_rwlock_node_irqsave lock; + + proc = find_process(pid, &lock); + if (!proc) { + /* This is normal behavior */ + dkprintf("%s: PID %d couldn't be found\n", __func__, pid); + return 0; + } + + __process_cleanup_fd(proc, fd); + + process_unlock(proc, &lock); + return 0; +} + +int process_cleanup_before_terminate(int pid) +{ + struct process *proc; + struct mcs_rwlock_node_irqsave lock; + int fd; + + proc = find_process(pid, &lock); + if (!proc) { + /* This is normal behavior */ + return 0; + } + + /* Clean up PDE file descriptors */ + for (fd = 2; fd < MAX_FD_PDE; ++fd) { + __process_cleanup_fd(proc, fd); + } + + process_unlock(proc, &lock); + return 0; +} + + void terminate_host(int pid, struct thread *thread) { @@ -4032,15 +4091,14 @@ SYSCALL_DECLARE(close) #ifdef ENABLE_TOFU /* Clear path and PDE data */ - if (fd >= 0 && fd < MAX_FD_PDE) { + if (thread->proc->enable_tofu && + fd >= 0 && fd < MAX_FD_PDE) { /* Tofu? */ if (thread->proc->fd_pde_data[fd]) { extern void tof_utofu_release_fd(struct process *proc, int fd); - if (thread->proc->fd_path[fd]) { - dkprintf("%s: -> tof_utofu_release_fd() @ fd: %d (%s)\n", - __func__, fd, thread->proc->fd_path[fd]); - } + dkprintf("%s: -> tof_utofu_release_fd() @ fd: %d (%s)\n", + __func__, fd, thread->proc->fd_path[fd]); tof_utofu_release_fd(thread->proc, fd); thread->proc->fd_pde_data[fd] = NULL; } diff --git a/kernel/tofu/tof_utofu_main.c b/kernel/tofu/tof_utofu_main.c index 88620f1f..ea819c56 100644 --- a/kernel/tofu/tof_utofu_main.c +++ b/kernel/tofu/tof_utofu_main.c @@ -896,16 +896,18 @@ static void tof_utofu_trans_update(struct tof_utofu_cq *ucq, int stag, uintptr_t struct tof_trans_table ent; uint64_t atomic; } tmp; + unsigned long flags; + tmp.ent.steering.bits.start = start >> PAGE_SHIFT; tmp.ent.steering.bits.len = len >> PAGE_SHIFT; tmp.ent.steering.bits.ps_code = (pgszbits == PAGE_SHIFT)? TOF_STAG_TRANS_PS_CODE_64KB:TOF_STAG_TRANS_PS_CODE_2MB; //atomic64_set((atomic64_t *)&table[stag], tmp.atomic); ihk_atomic64_set((ihk_atomic64_t *)&table[stag], tmp.atomic); - linux_spin_lock(&ucq->trans.mru_lock); + linux_spin_lock_irqsave(&ucq->trans.mru_lock, flags); tof_utofu_trans_mru_delete(ucq, stag); tof_utofu_trans_mru_insert(ucq, stag, pgszbits, mbpt); - linux_spin_unlock(&ucq->trans.mru_lock); + linux_spin_unlock_irqrestore(&ucq->trans.mru_lock, flags); } @@ -1009,6 +1011,7 @@ static int tof_utofu_ioctl_alloc_stag(struct tof_utofu_device *dev, unsigned lon uint8_t pgszbits; size_t pgsz; int ret = -ENOTSUPP; + unsigned long irqflags; ucq = container_of(dev, struct tof_utofu_cq, common); if(!ucq->common.enabled){ @@ -1054,9 +1057,9 @@ static int tof_utofu_ioctl_alloc_stag(struct tof_utofu_device *dev, unsigned lon #if 1 /* normal stag */ int stag; - linux_spin_lock(&ucq->trans.mru_lock); + linux_spin_lock_irqsave(&ucq->trans.mru_lock, irqflags); stag = tof_utofu_trans_search(ucq, start, end, pgszbits, readonly); - linux_spin_unlock(&ucq->trans.mru_lock); + linux_spin_unlock_irqrestore(&ucq->trans.mru_lock, irqflags); if(stag < 0){ struct tof_utofu_mbpt *mbpt = NULL; stag = tof_utofu_reserve_stag(ucq, readonly); @@ -1304,6 +1307,7 @@ static int tof_utofu_ioctl_free_stags(struct tof_utofu_device *dev, unsigned lon struct tof_free_stags req; int i, no_free_cnt = 0, ret; int stags[1024]; + unsigned long irqflags; ucq = container_of(dev, struct tof_utofu_cq, common); @@ -1325,9 +1329,9 @@ static int tof_utofu_ioctl_free_stags(struct tof_utofu_device *dev, unsigned lon } for(i = 0; i < req.num; i++){ - linux_spin_lock(&ucq->trans.mru_lock); + linux_spin_lock_irqsave(&ucq->trans.mru_lock, irqflags); ret = tof_utofu_free_stag(ucq, stags[i]); - linux_spin_unlock(&ucq->trans.mru_lock); + linux_spin_unlock_irqrestore(&ucq->trans.mru_lock, irqflags); if(ret == 0){ stags[i] = -1; } @@ -1372,6 +1376,7 @@ void tof_utofu_release_cq(void *pde_data) struct tof_utofu_cq *ucq; int stag; struct tof_utofu_device *dev; + unsigned long irqflags; dev = (struct tof_utofu_device *)pde_data; ucq = container_of(dev, struct tof_utofu_cq, common); @@ -1383,9 +1388,9 @@ void tof_utofu_release_cq(void *pde_data) } for (stag = 0; stag < TOF_UTOFU_NUM_STAG(ucq->num_stag); stag++) { - linux_spin_lock(&ucq->trans.mru_lock); + linux_spin_lock_irqsave(&ucq->trans.mru_lock, irqflags); tof_utofu_free_stag(ucq, stag); - linux_spin_unlock(&ucq->trans.mru_lock); + linux_spin_unlock_irqrestore(&ucq->trans.mru_lock, irqflags); } dkprintf("%s: UCQ (pde: %p) TNI %d, CQ %d\n", @@ -1911,6 +1916,8 @@ static int tof_utofu_disable_bch(struct tof_utofu_bg *ubg){ //tof_smmu_release_ipa_bg(ubg->tni, ubg->bgid, ubg->bch.iova, TOF_ICC_BCH_DMA_ALIGN); //put_page(ubg->bch.page); ubg->bch.enabled = false; + smp_mb(); + dkprintf("%s: tni=%d bgid=%d\n", __func__, ubg->tni, ubg->bgid); return 0; } @@ -2084,11 +2091,15 @@ void tof_utofu_release_fd(struct process *proc, int fd) return; } - if (strstr((const char *)proc->fd_path, "cq")) { + if (strstr((const char *)proc->fd_path[fd], "cq")) { + dkprintf("%s: PID: %d, fd: %d -> release CQ\n", + __func__, proc->pid, fd); tof_utofu_release_cq(proc->fd_pde_data[fd]); } - else if (strstr((const char *)proc->fd_path, "bch")) { + else if (strstr((const char *)proc->fd_path[fd], "bch")) { + dkprintf("%s: PID: %d, fd: %d -> release BCH\n", + __func__, proc->pid, fd); tof_utofu_release_bch(proc->fd_pde_data[fd]); } }