1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  26  */
  27 
  28 #include <sys/proc.h>
  29 #include <sys/cpuvar.h>
  30 #include <sys/disp.h>
  31 
  32 /*
  33  * Install process context ops for the current process.
  34  */
  35 void
  36 installpctx(
  37         proc_t *p,
  38         void    *arg,
  39         void    (*save)(void *),
  40         void    (*restore)(void *),
  41         void    (*fork)(void *, void *),
  42         void    (*exit)(void *),
  43         void    (*free)(void *, int))
  44 {
  45         struct pctxop *pctx;
  46 
  47         pctx = kmem_alloc(sizeof (struct pctxop), KM_SLEEP);
  48         pctx->save_op = save;
  49         pctx->restore_op = restore;
  50         pctx->fork_op = fork;
  51         pctx->exit_op = exit;
  52         pctx->free_op = free;
  53         pctx->arg = arg;
  54         pctx->next = p->p_pctx;
  55         p->p_pctx = pctx;
  56 }
  57 
  58 /*
  59  * Remove a process context ops from the current process.
  60  */
  61 int
  62 removepctx(
  63         proc_t *p,
  64         void    *arg,
  65         void    (*save)(void *),
  66         void    (*restore)(void *),
  67         void    (*fork)(void *, void *),
  68         void    (*exit)(void *),
  69         void    (*free)(void *, int))
  70 {
  71         struct pctxop *pctx, *prev_pctx;
  72 
  73         prev_pctx = NULL;
  74         kpreempt_disable();
  75         for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next) {
  76                 if (pctx->save_op == save && pctx->restore_op == restore &&
  77                     pctx->fork_op == fork &&
  78                     pctx->exit_op == exit && pctx->free_op == free &&
  79                     pctx->arg == arg) {
  80                         if (prev_pctx)
  81                                 prev_pctx->next = pctx->next;
  82                         else
  83                                 p->p_pctx = pctx->next;
  84                         if (pctx->free_op != NULL)
  85                                 (pctx->free_op)(pctx->arg, 0);
  86                         kmem_free(pctx, sizeof (struct pctxop));
  87                         kpreempt_enable();
  88                         return (1);
  89                 }
  90                 prev_pctx = pctx;
  91         }
  92         kpreempt_enable();
  93         return (0);
  94 }
  95 
  96 void
  97 savepctx(proc_t *p)
  98 {
  99         struct pctxop *pctx;
 100 
 101         ASSERT(p == curthread->t_procp);
 102         for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
 103                 if (pctx->save_op != NULL)
 104                         (pctx->save_op)(pctx->arg);
 105 }
 106 
 107 void
 108 restorepctx(proc_t *p)
 109 {
 110         struct pctxop *pctx;
 111 
 112         ASSERT(p == curthread->t_procp);
 113         for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
 114                 if (pctx->restore_op != NULL)
 115                         (pctx->restore_op)(pctx->arg);
 116 }
 117 
 118 void
 119 forkpctx(proc_t *p, proc_t *cp)
 120 {
 121         struct pctxop *pctx;
 122 
 123         for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
 124                 if (pctx->fork_op != NULL)
 125                         (pctx->fork_op)(p, cp);
 126 }
 127 
 128 /*
 129  * exitpctx is called during thread/lwp exit to perform any actions
 130  * needed when an LWP in the process leaves the processor for the last
 131  * time. This routine is not intended to deal with freeing memory; freepctx()
 132  * is used for that purpose during proc_exit(). This routine is provided to
 133  * allow for clean-up that can't wait until thread_free().
 134  */
 135 void
 136 exitpctx(proc_t *p)
 137 {
 138         struct pctxop *pctx;
 139 
 140         for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
 141                 if (pctx->exit_op != NULL)
 142                         (pctx->exit_op)(p);
 143 }
 144 
 145 /*
 146  * freepctx is called from proc_exit() to get rid of the actual context ops.
 147  */
 148 void
 149 freepctx(proc_t *p, int isexec)
 150 {
 151         struct pctxop *pctx;
 152 
 153         kpreempt_disable();
 154         while ((pctx = p->p_pctx) != NULL) {
 155                 p->p_pctx = pctx->next;
 156                 if (pctx->free_op != NULL)
 157                         (pctx->free_op)(pctx->arg, isexec);
 158                 kmem_free(pctx, sizeof (struct pctxop));
 159         }
 160         kpreempt_enable();
 161 }
 162 
 163 boolean_t
 164 secflag_enabled(proc_t *p, secflag_t flag)
 165 {
 166         return (secflag_isset(p->p_secflags.psf_effective, flag));
 167 }
 168 
 169 void
 170 secflags_promote(proc_t *p)
 171 {
 172         secflags_copy(&p->p_secflags.psf_effective, &p->p_secflags.psf_inherit);
 173 }