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, uint_t flag) 165 { 166 return ((p->p_secflags.psf_effective & flag) != 0); 167 } 168 169 void 170 secflag_set(proc_t *p, uint_t flag) 171 { 172 p->p_secflags.psf_inherit = flag; 173 } 174 175 void 176 secflag_enable(proc_t *p, uint_t flag) { 177 p->p_secflags.psf_inherit |= flag; 178 } 179 180 void 181 secflag_disable(proc_t *p, uint_t flag) { 182 p->p_secflags.psf_inherit &= ~flag; 183 } 184 185 void 186 secflag_promote(proc_t *p) { 187 p->p_secflags.psf_effective = p->p_secflags.psf_inherit; 188 }