/*
*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <vm/seg_kmem.h>
#include <sys/mem_config.h>
#include <sys/sysmacros.h>
extern pgcnt_t pp_dummy_npages;
extern kmutex_t memseg_lists_lock;
extern struct memseg *memseg_va_avail;
extern struct memseg *memseg_alloc();
static int sun4v_memseg_debug;
/*
* The page_t memory for incoming pages is allocated from existing memory
* which can create a potential situation where memory addition fails
* because of shortage of existing memory. To mitigate this situation
* some memory is always reserved ahead of time for page_t allocation.
* Each 4MB of reserved page_t's guarantees a 256MB (x64) addition without
* page_t allocation. The added 256MB added memory could theoretically
* allow an addition of 16GB.
*/
#ifdef DEBUG
#else
#define MEMSEG_DEBUG(...)
#endif
/*
* The page_t's for the incoming memory are allocated from
* existing pages.
*/
/*ARGSUSED*/
int
{
int i;
/*
* Verify incoming memory is within supported DR range.
*/
return (KPHYSM_ENOTSUP);
/*
* Another memseg has page_t's in the same
* page which 'pp' resides. This would happen
* if PAGESIZE is not an integral multiple of
* sizeof (page_t) and therefore 'pp'
* does not start on a page boundry.
*
* Since the other memseg's pages_t's still
* map valid pages, skip allocation of this page.
* Advance 'pp' to the next page which should
* belong only to the incoming memseg.
*
* If the last page_t in the current page
* crosses a page boundary, this should still
* work. The first part of the page_t is
* already allocated. The second part of
* the page_t will be allocated below.
*/
metapgs--;
}
/*
* Another memseg has page_t's in the same
* page which 'epp' resides. This would happen
* if PAGESIZE is not an integral multiple of
* sizeof (page_t) and therefore 'epp'
* does not start on a page boundry.
*
* Since the other memseg's pages_t's still
* map valid pages, skip allocation of this page.
*/
metapgs--;
}
/*
* Back metadata space with physical pages.
*/
for (i = 0; i < metapgs; i++)
panic("page_find(0x%p, %p)\n",
/*
* Allocate the metadata pages; these are the pages that will
* contain the page_t's for the incoming memory.
*/
MEMSEG_DEBUG("memseg_alloc_meta: can't get 0x%ld metapgs",
metapgs);
return (KPHYSM_ERESOURCE);
}
return (KPHYSM_OK);
}
void
{
int i;
if (!metapgs)
return;
MEMSEG_DEBUG("memseg_free_meta: off=0x%lx metapgs=0x%lx\n",
/*
* Free pages allocated during add.
*/
for (i = 0; i < metapgs; i++) {
page_destroy(pp, 0);
}
}
{
}
/*
* ends of the range if they are already in use.
*/
void
{
int i;
#if 0
#endif
#if 0
/*
* This code cannot be tested as the kernel does not compile
* when page_t size is changed. It is left here as a starting
* point if the unaligned page_t size needs to be supported.
*/
/*
* Another memseg has page_t's in the same
* page which 'pp' resides. This would happen
* if PAGESIZE is not an integral multiple of
* sizeof (page_t) and therefore 'seg->pages'
* does not start on a page boundry.
*
* Since the other memseg's pages_t's still
* map valid pages, skip remap of this page.
* Advance 'pp' to the next page which should
* belong only to the outgoing memseg.
*
* If the last page_t in the current page
* crosses a page boundary, this should still
* work. The first part of the page_t is
* valid since memseg_lock_delete_all() has
* been called. The second part of the page_t
* will be remapped to the corresponding
* dummy page below.
*/
metapgs--;
}
/*
* Another memseg has page_t's in the same
* page which 'epp' resides. This would happen
* if PAGESIZE is not an integral multiple of
* sizeof (page_t) and therefore 'seg->epages'
* does not start on a page boundry.
*
* Since the other memseg's pages_t's still
* map valid pages, skip remap of this page.
*/
metapgs--;
}
#endif
MEMSEG_DEBUG("memseg_remap_meta: off=0x%lx metapgs=0x%lx\n",
/*
* Free pages allocated during add.
*/
for (i = 0; i < metapgs; i++) {
page_destroy(pp, 0);
}
}