/*
* 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/platform_module.h>
#include <sys/sysmacros.h>
int mem_node_pfn_shift;
/*
* num_memnodes should be updated atomically and always >=
* the number of bits in memnodes_mask or the algorithm may fail.
*/
/*
* If set, mem_node_physalign should be a power of two, and
* should reflect the minimum address alignment of each node.
*/
/*
* Platform hooks we will need.
*/
/*
* Adjust the memnode config after a DR operation.
*
* It is rather tricky to do these updates since we can't
* protect the memnode structures with locks, so we must
* be mindful of the order in which updates and reads to
* these values can occur.
*/
void
{
int mnode;
/*
* DR will pass us the first pfn that is allocatable.
* We need to round down to get the real start of
* the slice.
*/
if (mem_node_physalign) {
}
/*
* Add slice to existing node.
*/
} else {
do {
oldmask);
}
/*
* Let the common lgrp framework know about the new memory
*/
}
/*
* Remove a PFN range from a memnode. On some platforms,
* the memnode will be created with physbase at the first
* allocatable PFN, but later deleted with the MC slice
* base address converted to a PFN, in which case we need
* to assume physbase and up.
*/
void
{
int mnode;
if (mem_node_physalign) {
}
if (node_size > delta_pgcnt) {
/*
* Subtract the slice from the memnode.
*/
} else {
/*
* Let the common lgrp framework know the mnode is
* leaving
*/
/*
* Delete the whole node.
*/
do {
}
}
void
{
if (&plat_slice_add != NULL)
else
}
void
{
if (&plat_slice_del != NULL)
else
}
void
{
/* LINTED: ASSERT will always true or false */
if (&plat_build_mem_nodes != NULL) {
} else {
/*
* Boot install lists are arranged <addr, len>, ...
*/
}
}
}
/*
* Allocate an unassigned memnode.
*/
int
{
int mnode;
/*
* Find an unused memnode. Update it atomically to prevent
* a first time memnode creation race.
*/
0, 1) == 0)
break;
if (mnode >= max_mem_nodes)
panic("Out of free memnodes\n");
do {
return (mnode);
}
/*
* Find the intersection between a memnode and a memlist
* and returns the number of pages that overlap.
*
* Grab the memlist lock to protect the list from DR operations.
*/
{
if (&plat_mem_node_intersect_range != NULL) {
}
return (npgs);
}
continue;
}
return (npgs);
}
/*
* Find MIN(physbase) and MAX(physmax) over all mnodes
*
* Called during startup and DR to find hpm_counters limits when
* interleaved_mnodes is set.
* NOTE: there is a race condition with DR if it tries to change more than
* one mnode in parallel. Sizing shared hpm_counters depends on finding the
* min(physbase) and max(physmax) across all mnodes. Therefore, the caller of
* page_ctrs_adjust must ensure that mem_node_config does not change while it
* is running.
*/
void
{
int mnode;
continue;
}
}