Haren Myneni's on March 19, 2020 4:16 pm:
> 
> When process opens a window, its pid and tgid will be saved in vas_window
> struct. This window will be closed when the process exits. Kernel handles
> NX faults by updating CSB or send SEGV signal to pid if user space csb_addr
> is invalid.

Bit of a nitpick, but can you use articles consistently ("the", "a")? I
won't keep nitpicking changelogs but I think they could be made easier 
to read. I'm happy to help proof read and suggest things offline when 
you're happy with the technical content of them, let me know.

> 
> In multi-thread applications, a window can be opened by child thread, but
> it will not be closed when this thread exits. Expects parent to clean up
> all resources including NX windows. Child thread can send requests using
> this window and can be killed before they are completed. But the pid
> assigned to this thread can be reused for other task while requests are
> pending. If the csb_addr passed in these requests is invalid, kernel will
> end up sending signal to the wrong task.
> 
> To prevent reusing the pid, take references to pid and mm when the window
> is opened and release them during window close.

We went over this together a while back, but task management isn't 
something I look at every day and it's complicated and easy to introduce
bugs. I suggest if we can get the changelog and comments written well
and understandable for someone who does not know or care about vas, 
then cc linux-kernel and the maintainers, and hopefully someone will 
take a look. It's not a large patch so if assumptions and concurrency
etc is documented, then it shouldn't be too much work.

Thanks,
Nick

> 
> Signed-off-by: Haren Myneni <ha...@linux.ibm.com>
> ---
>  arch/powerpc/platforms/powernv/vas-debug.c  |  2 +-
>  arch/powerpc/platforms/powernv/vas-window.c | 53 
> ++++++++++++++++++++++++++---
>  arch/powerpc/platforms/powernv/vas.h        |  9 ++++-
>  3 files changed, 57 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/powernv/vas-debug.c 
> b/arch/powerpc/platforms/powernv/vas-debug.c
> index 09e63df..ef9a717 100644
> --- a/arch/powerpc/platforms/powernv/vas-debug.c
> +++ b/arch/powerpc/platforms/powernv/vas-debug.c
> @@ -38,7 +38,7 @@ static int info_show(struct seq_file *s, void *private)
>  
>       seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
>                                       window->tx_win ? "Send" : "Receive");
> -     seq_printf(s, "Pid : %d\n", window->pid);
> +     seq_printf(s, "Pid : %d\n", vas_window_pid(window));
>  
>  unlock:
>       mutex_unlock(&vas_mutex);
> diff --git a/arch/powerpc/platforms/powernv/vas-window.c 
> b/arch/powerpc/platforms/powernv/vas-window.c
> index acb6a22..e7641a5 100644
> --- a/arch/powerpc/platforms/powernv/vas-window.c
> +++ b/arch/powerpc/platforms/powernv/vas-window.c
> @@ -12,6 +12,8 @@
>  #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"
> @@ -876,8 +878,6 @@ struct vas_window *vas_rx_win_open(int vasid, enum 
> vas_cop_type cop,
>       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);
> @@ -1027,7 +1027,6 @@ struct vas_window *vas_tx_win_open(int vasid, enum 
> vas_cop_type cop,
>       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;
>  
> @@ -1068,8 +1067,43 @@ struct vas_window *vas_tx_win_open(int vasid, enum 
> vas_cop_type cop,
>                       goto free_window;
>       }
>  
> -     set_vinst_win(vinst, txwin);
> +     if (txwin->user_win) {
> +             /*
> +              * Window opened by 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, child 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);
>       return txwin;
>  
>  free_window:
> @@ -1266,8 +1300,17 @@ int vas_win_close(struct vas_window *window)
>       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);
>  
> diff --git a/arch/powerpc/platforms/powernv/vas.h 
> b/arch/powerpc/platforms/powernv/vas.h
> index 310b8a0..16aa8ec 100644
> --- a/arch/powerpc/platforms/powernv/vas.h
> +++ b/arch/powerpc/platforms/powernv/vas.h
> @@ -353,7 +353,9 @@ struct vas_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;
> @@ -431,6 +433,11 @@ struct vas_winctx {
>  extern struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
>                                               uint32_t pswid);
>  
> +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)
>  {
> -- 
> 1.8.3.1
> 
> 
> 
> 

Reply via email to