7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24 /*
25 * Copyright (c) 2010, Intel Corporation.
26 * All rights reserved.
27 * Copyright 2016 Joyent, Inc.
28 */
29
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
32
33 /*
34 * Portions of this source code were derived from Berkeley 4.3 BSD
35 * under license from the Regents of the University of California.
36 */
37
38 /*
39 * UNIX machine dependent virtual memory support.
40 */
41
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/user.h>
46 #include <sys/proc.h>
47 #include <sys/kmem.h>
347 * Used by page layer to know about page sizes
348 */
349 hw_pagesize_t hw_page_array[MAX_NUM_LEVEL + 1];
350
351 kmutex_t *fpc_mutex[NPC_MUTEX];
352 kmutex_t *cpc_mutex[NPC_MUTEX];
353
354 /* Lock to protect mnoderanges array for memory DR operations. */
355 static kmutex_t mnoderange_lock;
356
357 /*
358 * Only let one thread at a time try to coalesce large pages, to
359 * prevent them from working against each other.
360 */
361 static kmutex_t contig_lock;
362 #define CONTIG_LOCK() mutex_enter(&contig_lock);
363 #define CONTIG_UNLOCK() mutex_exit(&contig_lock);
364
365 #define PFN_16M (mmu_btop((uint64_t)0x1000000))
366
367 /*
368 * Return the optimum page size for a given mapping
369 */
370 /*ARGSUSED*/
371 size_t
372 map_pgsz(int maptype, struct proc *p, caddr_t addr, size_t len, int memcntl)
373 {
374 level_t l = 0;
375 size_t pgsz = MMU_PAGESIZE;
376 size_t max_lpsize;
377 uint_t mszc;
378
379 ASSERT(maptype != MAPPGSZ_VA);
380
381 if (maptype != MAPPGSZ_ISM && physmem < privm_lpg_min_physmem) {
382 return (MMU_PAGESIZE);
383 }
384
385 switch (maptype) {
386 case MAPPGSZ_HEAP:
387 case MAPPGSZ_STK:
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24 /*
25 * Copyright (c) 2010, Intel Corporation.
26 * All rights reserved.
27 * Copyright 2018 Joyent, Inc.
28 */
29
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
32
33 /*
34 * Portions of this source code were derived from Berkeley 4.3 BSD
35 * under license from the Regents of the University of California.
36 */
37
38 /*
39 * UNIX machine dependent virtual memory support.
40 */
41
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/user.h>
46 #include <sys/proc.h>
47 #include <sys/kmem.h>
347 * Used by page layer to know about page sizes
348 */
349 hw_pagesize_t hw_page_array[MAX_NUM_LEVEL + 1];
350
351 kmutex_t *fpc_mutex[NPC_MUTEX];
352 kmutex_t *cpc_mutex[NPC_MUTEX];
353
354 /* Lock to protect mnoderanges array for memory DR operations. */
355 static kmutex_t mnoderange_lock;
356
357 /*
358 * Only let one thread at a time try to coalesce large pages, to
359 * prevent them from working against each other.
360 */
361 static kmutex_t contig_lock;
362 #define CONTIG_LOCK() mutex_enter(&contig_lock);
363 #define CONTIG_UNLOCK() mutex_exit(&contig_lock);
364
365 #define PFN_16M (mmu_btop((uint64_t)0x1000000))
366
367 caddr_t
368 i86devmap(pfn_t pf, pgcnt_t pgcnt, uint_t prot)
369 {
370 caddr_t addr;
371 caddr_t addr1;
372 page_t *pp;
373
374 addr1 = addr = vmem_alloc(heap_arena, mmu_ptob(pgcnt), VM_SLEEP);
375
376 for (; pgcnt != 0; addr += MMU_PAGESIZE, ++pf, --pgcnt) {
377 pp = page_numtopp_nolock(pf);
378 if (pp == NULL) {
379 hat_devload(kas.a_hat, addr, MMU_PAGESIZE, pf,
380 prot | HAT_NOSYNC, HAT_LOAD_LOCK);
381 } else {
382 hat_memload(kas.a_hat, addr, pp,
383 prot | HAT_NOSYNC, HAT_LOAD_LOCK);
384 }
385 }
386
387 return (addr1);
388 }
389
390 /*
391 * This routine is like page_numtopp, but accepts only free pages, which
392 * it allocates (unfrees) and returns with the exclusive lock held.
393 * It is used by machdep.c/dma_init() to find contiguous free pages.
394 */
395 page_t *
396 page_numtopp_alloc(pfn_t pfnum)
397 {
398 page_t *pp;
399
400 retry:
401 pp = page_numtopp_nolock(pfnum);
402 if (pp == NULL) {
403 return (NULL);
404 }
405
406 if (!page_trylock(pp, SE_EXCL)) {
407 return (NULL);
408 }
409
410 if (page_pptonum(pp) != pfnum) {
411 page_unlock(pp);
412 goto retry;
413 }
414
415 if (!PP_ISFREE(pp)) {
416 page_unlock(pp);
417 return (NULL);
418 }
419 if (pp->p_szc) {
420 page_demote_free_pages(pp);
421 page_unlock(pp);
422 goto retry;
423 }
424
425 /* If associated with a vnode, destroy mappings */
426
427 if (pp->p_vnode) {
428
429 page_destroy_free(pp);
430
431 if (!page_lock(pp, SE_EXCL, (kmutex_t *)NULL, P_NO_RECLAIM)) {
432 return (NULL);
433 }
434
435 if (page_pptonum(pp) != pfnum) {
436 page_unlock(pp);
437 goto retry;
438 }
439 }
440
441 if (!PP_ISFREE(pp)) {
442 page_unlock(pp);
443 return (NULL);
444 }
445
446 if (!page_reclaim(pp, (kmutex_t *)NULL))
447 return (NULL);
448
449 return (pp);
450 }
451
452 /*
453 * Return the optimum page size for a given mapping
454 */
455 /*ARGSUSED*/
456 size_t
457 map_pgsz(int maptype, struct proc *p, caddr_t addr, size_t len, int memcntl)
458 {
459 level_t l = 0;
460 size_t pgsz = MMU_PAGESIZE;
461 size_t max_lpsize;
462 uint_t mszc;
463
464 ASSERT(maptype != MAPPGSZ_VA);
465
466 if (maptype != MAPPGSZ_ISM && physmem < privm_lpg_min_physmem) {
467 return (MMU_PAGESIZE);
468 }
469
470 switch (maptype) {
471 case MAPPGSZ_HEAP:
472 case MAPPGSZ_STK:
|