Tofu: proper cleanup of device files when mcexec gets killed

Change-Id: I6cb0290f72d96682700f945b29585e132e525ac1
This commit is contained in:
Balazs Gerofi
2020-09-08 13:30:32 +09:00
committed by Masamichi Takagi
parent 1918df7765
commit e5f4a4e87d
10 changed files with 489 additions and 40 deletions

View File

@ -2,6 +2,7 @@
#include <linux/version.h>
#include <linux/mm_types.h>
#include <linux/kallsyms.h>
#include <linux/delay.h>
#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE
#include <linux/sched/task_stack.h>
#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);
}

View File

@ -36,6 +36,7 @@
#include <linux/semaphore.h>
#include <linux/interrupt.h>
#include <linux/cpumask.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/delay.h>
#include <asm/io.h>
@ -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);
}

View File

@ -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");
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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]);
}
}