1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include <sys/types.h> 31*0Sstevel@tonic-gate #include <sys/cmn_err.h> 32*0Sstevel@tonic-gate #include <sys/mman.h> 33*0Sstevel@tonic-gate #include <sys/systm.h> 34*0Sstevel@tonic-gate #include <vm/xhat.h> 35*0Sstevel@tonic-gate #include <vm/page.h> 36*0Sstevel@tonic-gate #include <vm/as.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate int xhat_debug = 0; 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate krwlock_t xhat_provider_rwlock; 41*0Sstevel@tonic-gate xhat_provider_t *xhat_provider = NULL; 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate void 44*0Sstevel@tonic-gate xhat_init() 45*0Sstevel@tonic-gate { 46*0Sstevel@tonic-gate rw_init(&xhat_provider_rwlock, NULL, RW_DEFAULT, NULL); 47*0Sstevel@tonic-gate } 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate int 52*0Sstevel@tonic-gate xhat_provider_register(xhat_provider_t *provider) 53*0Sstevel@tonic-gate { 54*0Sstevel@tonic-gate /* strlen("_cache") = 7 */ 55*0Sstevel@tonic-gate char cache_name[XHAT_CACHE_NAMELEN + 7]; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate if (provider->xhat_provider_version != XHAT_PROVIDER_VERSION) { 59*0Sstevel@tonic-gate cmn_err(CE_WARN, "XHAT provider version mismatch"); 60*0Sstevel@tonic-gate return (-1); 61*0Sstevel@tonic-gate } 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate if ((XHAT_POPS(provider)->xhat_alloc == NULL) || 64*0Sstevel@tonic-gate (XHAT_POPS(provider)->xhat_free == NULL)) { 65*0Sstevel@tonic-gate cmn_err(CE_WARN, "Malformed XHAT provider"); 66*0Sstevel@tonic-gate return (-1); 67*0Sstevel@tonic-gate } 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* Allocate kmem_cache which will manage xhat blocks */ 70*0Sstevel@tonic-gate provider->xblkcache->free_blks = NULL; 71*0Sstevel@tonic-gate (void) strncpy(cache_name, provider->xhat_provider_name, 72*0Sstevel@tonic-gate XHAT_CACHE_NAMELEN); 73*0Sstevel@tonic-gate (void) strcat(cache_name, "_cache"); 74*0Sstevel@tonic-gate provider->xblkcache->cache = kmem_cache_create(cache_name, 75*0Sstevel@tonic-gate provider->xhat_provider_blk_size, 0, NULL, NULL, 76*0Sstevel@tonic-gate provider->xblkcache->reclaim, 77*0Sstevel@tonic-gate (void *)provider, NULL, 0); 78*0Sstevel@tonic-gate if (provider->xblkcache->cache == NULL) { 79*0Sstevel@tonic-gate cmn_err(CE_WARN, "Failed to allocate cache for %s", 80*0Sstevel@tonic-gate provider->xhat_provider_name); 81*0Sstevel@tonic-gate return (-1); 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate mutex_init(&provider->xblkcache->lock, NULL, MUTEX_DEFAULT, NULL); 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate /* Insert provider in the global list */ 88*0Sstevel@tonic-gate rw_enter(&xhat_provider_rwlock, RW_WRITER); 89*0Sstevel@tonic-gate provider->next = xhat_provider; 90*0Sstevel@tonic-gate provider->prev = NULL; 91*0Sstevel@tonic-gate if (xhat_provider) 92*0Sstevel@tonic-gate xhat_provider->prev = provider; 93*0Sstevel@tonic-gate xhat_provider = provider; 94*0Sstevel@tonic-gate xhat_provider->xhat_provider_refcnt = 0; 95*0Sstevel@tonic-gate rw_exit(&xhat_provider_rwlock); 96*0Sstevel@tonic-gate return (0); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate int 102*0Sstevel@tonic-gate xhat_provider_unregister(xhat_provider_t *provider) 103*0Sstevel@tonic-gate { 104*0Sstevel@tonic-gate if (provider->xhat_provider_version != XHAT_PROVIDER_VERSION) 105*0Sstevel@tonic-gate return (-1); 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate rw_enter(&xhat_provider_rwlock, RW_WRITER); 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate if (provider->xhat_provider_refcnt) { 110*0Sstevel@tonic-gate rw_exit(&xhat_provider_rwlock); 111*0Sstevel@tonic-gate return (-1); 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate if (provider->next) 115*0Sstevel@tonic-gate provider->next->prev = provider->prev; 116*0Sstevel@tonic-gate if (provider->prev) 117*0Sstevel@tonic-gate provider->prev->next = provider->next; 118*0Sstevel@tonic-gate else 119*0Sstevel@tonic-gate xhat_provider = provider->next; 120*0Sstevel@tonic-gate provider->prev = NULL; 121*0Sstevel@tonic-gate provider->next = NULL; 122*0Sstevel@tonic-gate rw_exit(&xhat_provider_rwlock); 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate /* Free all xblks that are sitting on free_blks list */ 125*0Sstevel@tonic-gate provider->xblkcache->reclaim(provider); 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate kmem_cache_destroy(provider->xblkcache->cache); 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate return (0); 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* Attaches an XHAT to the address space */ 135*0Sstevel@tonic-gate int 136*0Sstevel@tonic-gate xhat_attach_xhat(xhat_provider_t *provider, struct as *as, 137*0Sstevel@tonic-gate struct xhat **xhatp, void *arg) 138*0Sstevel@tonic-gate { 139*0Sstevel@tonic-gate struct xhat *xh; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate xh = XHAT_POPS(provider)->xhat_alloc(arg); 144*0Sstevel@tonic-gate if (xh == NULL) { 145*0Sstevel@tonic-gate *xhatp = NULL; 146*0Sstevel@tonic-gate return (XH_PRVDR); 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate mutex_init(&xh->xhat_lock, NULL, MUTEX_DEFAULT, NULL); 150*0Sstevel@tonic-gate xh->xhat_provider = provider; 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate rw_enter(&xhat_provider_rwlock, RW_WRITER); 153*0Sstevel@tonic-gate provider->xhat_provider_refcnt++; 154*0Sstevel@tonic-gate rw_exit(&xhat_provider_rwlock); 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate /* Is address space busy (being freed, dup'd or swapped)? */ 159*0Sstevel@tonic-gate if (AS_ISBUSY(as)) { 160*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 161*0Sstevel@tonic-gate XHAT_POPS(provider)->xhat_free(xh); 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate rw_enter(&xhat_provider_rwlock, RW_WRITER); 164*0Sstevel@tonic-gate provider->xhat_provider_refcnt--; 165*0Sstevel@tonic-gate rw_exit(&xhat_provider_rwlock); 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate *xhatp = NULL; 168*0Sstevel@tonic-gate return (XH_ASBUSY); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate xh->xhat_as = as; 172*0Sstevel@tonic-gate xh->xhat_refcnt = 0; 173*0Sstevel@tonic-gate xh->holder = NULL; 174*0Sstevel@tonic-gate xh->arg = arg; 175*0Sstevel@tonic-gate xh->next = (struct xhat *)as->a_xhat; 176*0Sstevel@tonic-gate if (xh->next) 177*0Sstevel@tonic-gate xh->next->prev = xh; 178*0Sstevel@tonic-gate as->a_xhat = xh; 179*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 180*0Sstevel@tonic-gate *xhatp = xh; 181*0Sstevel@tonic-gate return (0); 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate int 186*0Sstevel@tonic-gate xhat_detach_xhat(xhat_provider_t *provider, struct as *as) 187*0Sstevel@tonic-gate { 188*0Sstevel@tonic-gate struct xhat *xh; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate for (xh = (struct xhat *)as->a_xhat; xh != NULL; xh = xh->next) 194*0Sstevel@tonic-gate if (xh->xhat_provider == provider) { 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate if (xh->holder != NULL) { 198*0Sstevel@tonic-gate /* 199*0Sstevel@tonic-gate * The address space is being freed, 200*0Sstevel@tonic-gate * dup'd or swapped out. 201*0Sstevel@tonic-gate * If we are the thread which doing one 202*0Sstevel@tonic-gate * of those operations, we can go ahead 203*0Sstevel@tonic-gate * and free up the XHAT. 204*0Sstevel@tonic-gate * Otherwise, return. 205*0Sstevel@tonic-gate */ 206*0Sstevel@tonic-gate if (xh->holder != curthread) { 207*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 208*0Sstevel@tonic-gate return (XH_ASBUSY); 209*0Sstevel@tonic-gate } else 210*0Sstevel@tonic-gate xhat_hat_rele(xh); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate if (xh->xhat_refcnt > 0) { 214*0Sstevel@tonic-gate /* 215*0Sstevel@tonic-gate * There are still "users" of the XHAT. 216*0Sstevel@tonic-gate * This may be either because the caller 217*0Sstevel@tonic-gate * forgot to free something up (which is a bug) 218*0Sstevel@tonic-gate * or because xhat_op_all() is in progress. 219*0Sstevel@tonic-gate * Since we are not allowing any of 220*0Sstevel@tonic-gate * xhat_op_all's ops to call xhat_detach_xhat(), 221*0Sstevel@tonic-gate * This can only be some other thread. It 222*0Sstevel@tonic-gate * may want to wait a bit and retry. 223*0Sstevel@tonic-gate */ 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate /* Restore the hold on the XHAT */ 227*0Sstevel@tonic-gate if (xh->holder == curthread) 228*0Sstevel@tonic-gate xhat_hat_hold(xh); 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 231*0Sstevel@tonic-gate return (XH_XHHELD); 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate rw_enter(&xhat_provider_rwlock, RW_WRITER); 235*0Sstevel@tonic-gate provider->xhat_provider_refcnt--; 236*0Sstevel@tonic-gate rw_exit(&xhat_provider_rwlock); 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate if (xh->next) 239*0Sstevel@tonic-gate xh->next->prev = xh->prev; 240*0Sstevel@tonic-gate if (xh->prev) 241*0Sstevel@tonic-gate xh->prev->next = xh->next; 242*0Sstevel@tonic-gate else 243*0Sstevel@tonic-gate as->a_xhat = (void *) xh->next; 244*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate XHAT_POPS(provider)->xhat_free(xh); 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate return (0); 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 251*0Sstevel@tonic-gate return (XH_NOTATTCHD); 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate void 255*0Sstevel@tonic-gate xhat_hat_hold(struct xhat *xhat) 256*0Sstevel@tonic-gate { 257*0Sstevel@tonic-gate mutex_enter(&xhat->xhat_lock); 258*0Sstevel@tonic-gate xhat->xhat_refcnt++; 259*0Sstevel@tonic-gate mutex_exit(&xhat->xhat_lock); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate void 263*0Sstevel@tonic-gate xhat_hat_rele(struct xhat *xhat) 264*0Sstevel@tonic-gate { 265*0Sstevel@tonic-gate mutex_enter(&xhat->xhat_lock); 266*0Sstevel@tonic-gate xhat->xhat_refcnt--; 267*0Sstevel@tonic-gate ASSERT(xhat->xhat_refcnt >= 0); 268*0Sstevel@tonic-gate mutex_exit(&xhat->xhat_lock); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate int 273*0Sstevel@tonic-gate xhat_hat_holders(struct xhat *xhat) 274*0Sstevel@tonic-gate { 275*0Sstevel@tonic-gate return (xhat->xhat_refcnt); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* 280*0Sstevel@tonic-gate * Assumes that address space is already locked 281*0Sstevel@tonic-gate * and that AS_FREE is set for as->a_flags. 282*0Sstevel@tonic-gate */ 283*0Sstevel@tonic-gate void 284*0Sstevel@tonic-gate xhat_free_start_all(struct as *as) 285*0Sstevel@tonic-gate { 286*0Sstevel@tonic-gate struct xhat *xh, *xh_nxt; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate ASSERT(AS_ISBUSY(as)); 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 292*0Sstevel@tonic-gate xh = (struct xhat *)as->a_xhat; 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate /* 295*0Sstevel@tonic-gate * Simply calling xhat_hat_hold() won't work because we will 296*0Sstevel@tonic-gate * not be able to succeed in xhat_detach_xhat(), which may 297*0Sstevel@tonic-gate * get called from here. We need to know _who_ the holder is. 298*0Sstevel@tonic-gate */ 299*0Sstevel@tonic-gate if (xh != NULL) { 300*0Sstevel@tonic-gate xhat_hat_hold(xh); 301*0Sstevel@tonic-gate ASSERT(xh->holder == NULL); 302*0Sstevel@tonic-gate xh->holder = curthread; 303*0Sstevel@tonic-gate } 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate while (xh != NULL) { 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate xh_nxt = xh->next; 308*0Sstevel@tonic-gate if (xh_nxt != NULL) { 309*0Sstevel@tonic-gate ASSERT(xh_nxt->holder == NULL); 310*0Sstevel@tonic-gate xhat_hat_hold(xh_nxt); 311*0Sstevel@tonic-gate xh_nxt->holder = curthread; 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate XHAT_FREE_START(xh); 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate xh = xh_nxt; 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate /* 329*0Sstevel@tonic-gate * Assumes that address space is already locked. 330*0Sstevel@tonic-gate * Since xhat_free_start_all() must have been called 331*0Sstevel@tonic-gate * earlier, for all XHATs holder is set to curthread. 332*0Sstevel@tonic-gate * Also, since AS_BUSY is set for as->a_flags, no new 333*0Sstevel@tonic-gate * XHATs could have been added. 334*0Sstevel@tonic-gate */ 335*0Sstevel@tonic-gate void 336*0Sstevel@tonic-gate xhat_free_end_all(struct as *as) 337*0Sstevel@tonic-gate { 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate struct xhat *xh, *xh_nxt; 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate ASSERT(AS_ISBUSY(as)); 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 344*0Sstevel@tonic-gate xh = (struct xhat *)as->a_xhat; 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate while (xh != NULL) { 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate ASSERT(xh->holder == curthread); 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate xh_nxt = xh->next; 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate XHAT_FREE_END(xh); 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate xh = xh_nxt; 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate /* Assumes that address space is already locked */ 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate /* ARGSUSED */ 369*0Sstevel@tonic-gate int 370*0Sstevel@tonic-gate xhat_dup_all(struct as *as, struct as *newas, caddr_t addr, size_t len, 371*0Sstevel@tonic-gate uint_t flag) 372*0Sstevel@tonic-gate { 373*0Sstevel@tonic-gate /* This is not supported. Should we return some sort of error? */ 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate ASSERT(AS_ISBUSY(as)); 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate return (0); 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate /* Assumes that address space is already locked */ 382*0Sstevel@tonic-gate void 383*0Sstevel@tonic-gate xhat_swapout_all(struct as *as) 384*0Sstevel@tonic-gate { 385*0Sstevel@tonic-gate struct xhat *xh, *xh_nxt; 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate ASSERT(AS_ISBUSY(as)); 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 391*0Sstevel@tonic-gate xh = (struct xhat *)as->a_xhat; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate if (xh != NULL) { 394*0Sstevel@tonic-gate xhat_hat_hold(xh); 395*0Sstevel@tonic-gate ASSERT(xh->holder == NULL); 396*0Sstevel@tonic-gate xh->holder = curthread; 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate while (xh != NULL) { 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate xh_nxt = xh->next; 403*0Sstevel@tonic-gate if (xh_nxt != NULL) { 404*0Sstevel@tonic-gate ASSERT(xh_nxt->holder == NULL); 405*0Sstevel@tonic-gate xhat_hat_hold(xh_nxt); 406*0Sstevel@tonic-gate xh_nxt->holder = curthread; 407*0Sstevel@tonic-gate } 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate XHAT_SWAPOUT(xh); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate /* 416*0Sstevel@tonic-gate * If the xh is still there (i.e. swapout did not 417*0Sstevel@tonic-gate * destroy it), clear the holder field. 418*0Sstevel@tonic-gate * xh_nxt->prev couldn't have been changed in xhat_attach_xhat() 419*0Sstevel@tonic-gate * because AS_BUSY is set. xhat_detach_xhat() also couldn't 420*0Sstevel@tonic-gate * have modified it because (holder != NULL). 421*0Sstevel@tonic-gate * If there is only one XHAT, just see if a_xhat still 422*0Sstevel@tonic-gate * points to us. 423*0Sstevel@tonic-gate */ 424*0Sstevel@tonic-gate if (((xh_nxt != NULL) && (xh_nxt->prev == xh)) || 425*0Sstevel@tonic-gate ((as->a_xhat != NULL) && (as->a_xhat == xh))) { 426*0Sstevel@tonic-gate xhat_hat_rele(xh); 427*0Sstevel@tonic-gate xh->holder = NULL; 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate xh = xh_nxt; 431*0Sstevel@tonic-gate } 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate /* 440*0Sstevel@tonic-gate * In the following routines, the appropriate xhat_op 441*0Sstevel@tonic-gate * should never attempt to call xhat_detach_xhat(): it will 442*0Sstevel@tonic-gate * never succeed since the XHAT is held. 443*0Sstevel@tonic-gate */ 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate #define XHAT_UNLOAD_CALLBACK_OP (0) 447*0Sstevel@tonic-gate #define XHAT_SETATTR_OP (1) 448*0Sstevel@tonic-gate #define XHAT_CLRATTR_OP (2) 449*0Sstevel@tonic-gate #define XHAT_CHGATTR_OP (3) 450*0Sstevel@tonic-gate #define XHAT_CHGPROT_OP (4) 451*0Sstevel@tonic-gate #define XHAT_UNSHARE_OP (5) 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate static void 455*0Sstevel@tonic-gate xhat_op_all(int op, struct as *as, caddr_t addr, 456*0Sstevel@tonic-gate size_t len, uint_t flags, void *ptr) 457*0Sstevel@tonic-gate { 458*0Sstevel@tonic-gate struct xhat *xh, *xh_nxt; 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 461*0Sstevel@tonic-gate xh = (struct xhat *)as->a_xhat; 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate while (xh != NULL) { 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate xhat_hat_hold(xh); 466*0Sstevel@tonic-gate 467*0Sstevel@tonic-gate xh_nxt = xh->next; 468*0Sstevel@tonic-gate if (xh_nxt != NULL) 469*0Sstevel@tonic-gate xhat_hat_hold(xh_nxt); 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate switch (op) { 474*0Sstevel@tonic-gate case XHAT_UNLOAD_CALLBACK_OP: 475*0Sstevel@tonic-gate XHAT_UNLOAD_CALLBACK(xh, addr, 476*0Sstevel@tonic-gate len, flags, (hat_callback_t *)ptr); 477*0Sstevel@tonic-gate break; 478*0Sstevel@tonic-gate case XHAT_SETATTR_OP: 479*0Sstevel@tonic-gate XHAT_SETATTR(xh, addr, len, flags); 480*0Sstevel@tonic-gate break; 481*0Sstevel@tonic-gate case XHAT_CLRATTR_OP: 482*0Sstevel@tonic-gate XHAT_CLRATTR(xh, addr, len, flags); 483*0Sstevel@tonic-gate break; 484*0Sstevel@tonic-gate case XHAT_CHGATTR_OP: 485*0Sstevel@tonic-gate XHAT_CHGATTR(xh, addr, len, flags); 486*0Sstevel@tonic-gate break; 487*0Sstevel@tonic-gate case XHAT_CHGPROT_OP: 488*0Sstevel@tonic-gate XHAT_CHGPROT(xh, addr, len, flags); 489*0Sstevel@tonic-gate break; 490*0Sstevel@tonic-gate case XHAT_UNSHARE_OP: 491*0Sstevel@tonic-gate XHAT_UNSHARE(xh, addr, len); 492*0Sstevel@tonic-gate break; 493*0Sstevel@tonic-gate default: 494*0Sstevel@tonic-gate panic("Unknown op %d in xhat_op_all", op); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate mutex_enter(&as->a_contents); 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate /* 500*0Sstevel@tonic-gate * Both pointers are still valid because both 501*0Sstevel@tonic-gate * XHATs are held. 502*0Sstevel@tonic-gate */ 503*0Sstevel@tonic-gate xhat_hat_rele(xh); 504*0Sstevel@tonic-gate if (xh_nxt != NULL) 505*0Sstevel@tonic-gate xhat_hat_rele(xh_nxt); 506*0Sstevel@tonic-gate xh = xh_nxt; 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate mutex_exit(&as->a_contents); 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate void 515*0Sstevel@tonic-gate xhat_unload_callback_all(struct as *as, caddr_t addr, size_t len, uint_t flags, 516*0Sstevel@tonic-gate hat_callback_t *callback) 517*0Sstevel@tonic-gate { 518*0Sstevel@tonic-gate xhat_op_all(XHAT_UNLOAD_CALLBACK_OP, as, addr, len, flags, callback); 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate void 523*0Sstevel@tonic-gate xhat_setattr_all(struct as *as, caddr_t addr, size_t len, uint_t attr) 524*0Sstevel@tonic-gate { 525*0Sstevel@tonic-gate xhat_op_all(XHAT_SETATTR_OP, as, addr, len, attr, NULL); 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate void 531*0Sstevel@tonic-gate xhat_clrattr_all(struct as *as, caddr_t addr, size_t len, uint_t attr) 532*0Sstevel@tonic-gate { 533*0Sstevel@tonic-gate xhat_op_all(XHAT_CLRATTR_OP, as, addr, len, attr, NULL); 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate void 538*0Sstevel@tonic-gate xhat_chgattr_all(struct as *as, caddr_t addr, size_t len, uint_t attr) 539*0Sstevel@tonic-gate { 540*0Sstevel@tonic-gate xhat_op_all(XHAT_CHGATTR_OP, as, addr, len, attr, NULL); 541*0Sstevel@tonic-gate } 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate void 545*0Sstevel@tonic-gate xhat_chgprot_all(struct as *as, caddr_t addr, size_t len, uint_t prot) 546*0Sstevel@tonic-gate { 547*0Sstevel@tonic-gate xhat_op_all(XHAT_CHGPROT_OP, as, addr, len, prot, NULL); 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate void 552*0Sstevel@tonic-gate xhat_unshare_all(struct as *as, caddr_t addr, size_t len) 553*0Sstevel@tonic-gate { 554*0Sstevel@tonic-gate xhat_op_all(XHAT_UNSHARE_OP, as, addr, len, 0, NULL); 555*0Sstevel@tonic-gate } 556