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