/**
 * Allocates one page.
 *
 * @param virtAddr       The virtual address to which this page maybe mapped in
 *                       the future.
 *
 * @returns Pointer to the allocated page, NULL on failure.
 */
static page_t *rtR0MemObjSolPageAlloc(caddr_t virtAddr)
{
    u_offset_t      offPage;
    seg_t           KernelSeg;

    /*
     * 16777215 terabytes of total memory for all VMs or
     * restart 8000 1GB VMs 2147483 times until wraparound!
     */
    mutex_enter(&g_OffsetMtx);
    AssertCompileSize(u_offset_t, sizeof(uint64_t)); NOREF(RTASSERTVAR);
    g_offPage = RT_ALIGN_64(g_offPage, PAGE_SIZE) + PAGE_SIZE;
    offPage   = g_offPage;
    mutex_exit(&g_OffsetMtx);

    KernelSeg.s_as = &kas;
    page_t *pPage = page_create_va(&g_PageVnode, offPage, PAGE_SIZE, PG_WAIT | PG_NORELOC, &KernelSeg, virtAddr);
    if (RT_LIKELY(pPage))
    {
        /*
         * Lock this page into memory "long term" to prevent this page from being paged out
         * when we drop the page lock temporarily (during free). Downgrade to a shared lock
         * to prevent page relocation.
         */
        page_pp_lock(pPage, 0 /* COW */, 1 /* Kernel */);
        page_io_unlock(pPage);
        page_downgrade(pPage);
        Assert(PAGE_LOCKED_SE(pPage, SE_SHARED));
    }

    return pPage;
}
Beispiel #2
0
static void
less_pages(uint64_t base, uint64_t len)
{
	uint64_t pa, end = base + len;
	extern int kcage_on;

	for (pa = base; pa < end; pa += PAGESIZE) {
		pfn_t pfnum;
		page_t *pp;

		pfnum = (pfn_t)(pa >> PAGESHIFT);
		if ((pp = page_numtopp_nolock(pfnum)) == NULL)
			cmn_err(CE_PANIC, "missing pfnum %lx", pfnum);

		/*
		 * must break up any large pages that may have
		 * constituent pages being utilized for
		 * prom_alloc()'s. page_reclaim() can't handle
		 * large pages.
		 */
		if (pp->p_szc != 0)
			page_boot_demote(pp);

		if (!PAGE_LOCKED(pp) && pp->p_lckcnt == 0) {
			/*
			 * Ahhh yes, a prom page,
			 * suck it off the freelist,
			 * lock it, and hashin on prom_pages vp.
			 */
			if (page_trylock(pp, SE_EXCL) == 0)
				cmn_err(CE_PANIC, "prom page locked");

			(void) page_reclaim(pp, NULL);
			/*
			 * vnode offsets on the prom_ppages vnode
			 * are page numbers (gack) for >32 bit
			 * physical memory machines.
			 */
			(void) page_hashin(pp, &promvp,
			    (offset_t)pfnum, NULL);

			if (kcage_on) {
				ASSERT(pp->p_szc == 0);
				if (PP_ISNORELOC(pp) == 0) {
					PP_SETNORELOC(pp);
					PLCNT_XFER_NORELOC(pp);
				}
			}
			(void) page_pp_lock(pp, 0, 1);
		}
	}
}