#include <linux/log2.h>
 #include <linux/rcupdate.h>
 #include <linux/cred.h>
+#include <linux/sched/mm.h>
+#include <linux/mmu_context.h>
 #include <asm/switch_to.h>
 #include <asm/ppc-opcode.h>
 #include "vas.h"
        rxwin->user_win = rxattr->user_win;
        rxwin->cop = cop;
        rxwin->wcreds_max = rxattr->wcreds_max ?: VAS_WCREDS_DEFAULT;
-       if (rxattr->user_win)
-               rxwin->pid = task_pid_vnr(current);
 
        init_winctx_for_rxwin(rxwin, rxattr, &winctx);
        init_winctx_regs(rxwin, &winctx);
        txwin->tx_win = 1;
        txwin->rxwin = rxwin;
        txwin->nx_win = txwin->rxwin->nx_win;
-       txwin->pid = attr->pid;
        txwin->user_win = attr->user_win;
        txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT;
 
                rc = set_thread_uses_vas();
                if (rc)
                        goto free_window;
+
+               /*
+                * Window opened by a child thread may not be closed when
+                * it exits. So take reference to its pid and release it
+                * when the window is free by parent thread.
+                * Acquire a reference to the task's pid to make sure
+                * pid will not be re-used - needed only for multithread
+                * applications.
+                */
+               txwin->pid = get_task_pid(current, PIDTYPE_PID);
+               /*
+                * Acquire a reference to the task's mm.
+                */
+               txwin->mm = get_task_mm(current);
+
+               if (!txwin->mm) {
+                       put_pid(txwin->pid);
+                       pr_err("VAS: pid(%d): mm_struct is not found\n",
+                                       current->pid);
+                       rc = -EPERM;
+                       goto free_window;
+               }
+
+               mmgrab(txwin->mm);
+               mmput(txwin->mm);
+               mm_context_add_copro(txwin->mm);
+               /*
+                * Process closes window during exit. In the case of
+                * multithread application, the child thread can open
+                * window and can exit without closing it. Expects parent
+                * thread to use and close the window. So do not need
+                * to take pid reference for parent thread.
+                */
+               txwin->tgid = find_get_pid(task_tgid_vnr(current));
        }
 
        set_vinst_win(vinst, txwin);
        poll_window_castout(window);
 
        /* if send window, drop reference to matching receive window */
-       if (window->tx_win)
+       if (window->tx_win) {
+               if (window->user_win) {
+                       /* Drop references to pid and mm */
+                       put_pid(window->pid);
+                       if (window->mm) {
+                               mm_context_remove_copro(window->mm);
+                               mmdrop(window->mm);
+                       }
+               }
                put_rx_win(window->rxwin);
+       }
 
        vas_window_free(window);
 
 
        bool user_win;          /* True if user space window */
        void *hvwc_map;         /* HV window context */
        void *uwc_map;          /* OS/User window context */
-       pid_t pid;              /* Linux process id of owner */
+       struct pid *pid;        /* Linux process id of owner */
+       struct pid *tgid;       /* Thread group ID of owner */
+       struct mm_struct *mm;   /* Linux process mm_struct */
        int wcreds_max;         /* Window credits */
 
        char *dbgname;
 extern void vas_window_free_dbgdir(struct vas_window *win);
 extern int vas_setup_fault_window(struct vas_instance *vinst);
 
+static inline int vas_window_pid(struct vas_window *window)
+{
+       return pid_vnr(window->pid);
+}
+
 static inline void vas_log_write(struct vas_window *win, char *name,
                        void *regptr, u64 val)
 {