bitmap.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 1999-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/prom_plat.h>
#include "cprboot.h"
/*
* max space for a copy of physavail data
* prop size is usually 80 to 128 bytes
*/
#define PA_BUFSIZE 1024
#define CB_SETBIT 1
#define CB_ISSET 2
#define CB_ISCLR 3
/*
* globals
*/
int cb_nbitmaps;
/*
* file scope
*/
static arange_t *cb_physavail;
static char pabuf[PA_BUFSIZE];
static int tracking_init;
static int
{
char *bitmap;
break;
}
}
return (rval);
}
/*
* count pages that are isolated from the kernel
* within each available range
*/
static void
count_free_pages(void)
{
int cnt;
cnt = 0;
cnt++;
}
}
}
/*
* scan the physavail list for a page
* that doesn't clash with the kernel
*/
static pfn_t
search_phav_pages(void)
{
int rescan;
arp = cb_physavail;
}
/*
* begin scanning from the previous position and if the scan
* reaches the end of the list, scan a second time from the top;
* nfree is checked to eliminate scanning overhead when most
* of the available space gets used up. when a page is found,
* set a bit so the page wont be found by another scan.
*/
continue;
return (bitno++);
}
}
}
arp = cb_physavail;
}
return (PFN_INVALID);
}
/*
* scan statefile buffer pages for reusable tmp space
*/
static pfn_t
search_buf_pages(void)
{
if (tracking_init == 0)
return (PFN_INVALID);
/*
* when scanning the list of statefile buffer ppns, we know that
* all pages from lboff to the page boundary of buf_offset have
* already been restored; when the associated page bit is clear,
* that page is isolated from the kernel and we can reuse it for
* tmp space; otherwise, when SF_DIFF_PPN indicates a page had
* been moved, we know the page bit was previously clear and
* later set, and we can reuse the new page.
*/
lboff += MMU_PAGESIZE;
return (ppn);
} else if (SF_DIFF_PPN(coff)) {
return (SF_BUF_PPN(coff));
}
}
return (PFN_INVALID);
}
/*
* scan physavail and statefile buffer page lists
* for a page that doesn't clash with the kernel
*/
find_apage(void)
{
ppn = search_phav_pages();
if (ppn != PFN_INVALID)
return (ppn);
ppn = search_buf_pages();
if (ppn != PFN_INVALID)
return (ppn);
prom_printf("\n%s: ran out of available/free pages!\n%s\n",
/* NOTREACHED */
return (PFN_INVALID);
}
/*
* reserve virt range, find available phys pages,
* and map-in each phys starting at vaddr
*/
static caddr_t
{
char *str;
str = "map_free_phys";
CB_VPRINTF(("\n%s: claim vaddr 0x%x, size 0x%x, ret 0x%x\n",
prom_printf("\n%s: cant reserve (0x%p - 0x%p) for \"%s\"\n",
return (virt);
}
/*
* map virt page to free phys
*/
ppn = find_apage();
prom_printf(" map virt 0x%p, phys 0x%lx, "
}
if (err)
}
return (vaddr);
}
/*
* check bitmap desc and relocate bitmap data
* to pages isolated from the kernel
*
* sets globals:
* high_virt
*/
int
cb_set_bitmap(void)
{
char *str;
str = "cb_set_bitmap";
/*
* max is checked in the cpr module;
* this condition should never occur
*/
prom_printf("%s: too many bitmap descriptors %d, max %d\n",
return (ERR);
}
/*
* copy bitmap descriptors to aligned space, check magic numbers,
* and set the total size of all bitmaps
*/
all_bitmap_size = 0;
prom_printf("%s: bad magic 0x%x, expect 0x%x\n",
return (ERR);
}
}
/*
* reserve new space for bitmaps
*/
prom_printf("%s: nbitmaps %d, bmda_size 0x%lx\n",
str, cb_nbitmaps);
prom_printf("%s: all_bitmap_size 0x%lx, alloc_size 0x%lx\n",
}
return (ERR);
/*
* copy the bitmaps, clear any unused space trailing them,
* and set references into the new space
*/
if (alloc_size > all_bitmap_size)
}
/* advance past all the bitmap data */
high_virt += alloc_size;
return (0);
}
/*
* create a new stack for cprboot;
* this stack is used to avoid clashes with kernel pages and
* to avoid exceptions while remapping cprboot virt pages
*/
int
cb_get_newstack(void)
{
CB_STACK_SIZE, "new stack");
return (ERR);
return (0);
}
/*
* since kernel phys pages span most of the installed memory range,
* some statefile buffer pages will likely clash with the kernel
* and need to be moved before kernel pages are restored; a list
* of buf phys page numbers is created here and later updated as
* buf pages are moved
*
* sets globals:
* sfile.buf_map
* tracking_init
*/
int
cb_tracking_setup(void)
{
int pages;
return (ERR);
/*
* create identity map of sfile.buf phys pages
*/
tracking_init = 1;
return (0);
}
/*
* get "available" prop from /memory node
*
* sets globals:
* cb_physavail
*/
int
cb_get_physavail(void)
{
int err;
str = "cb_get_physavail";
/*
* first move cprboot pages off the physavail list
*/
CB_VPRINTF((" text/data claim (0x%lx - 0x%lx) = %d\n",
if (err)
return (ERR);
pdev = "/memory";
if (mem_node == OBP_BADNODE) {
return (ERR);
}
mem_prop = "available";
/*
* prop data is treated as a struct array;
* verify pabuf has enough room for the array
* in the original and converted forms
*/
prom_printf("\n%s: bad \"%s\" length %d, min %d, max %d\n",
return (ERR);
}
/*
* read-in prop data and clear trailing space
*/
prom_printf("\n%s: %s,%s: expected len %d, got %d\n",
return (ERR);
}
/*
* convert the physavail list in place
* from (phys_base, phys_size) to (low_ppn, high_ppn)
*/
if (verbose)
prom_printf("\nphysavail list:\n");
if (verbose) {
prom_printf(" %d: (0x%lx - 0x%lx),\tpages %d\n",
(int)(arp - cb_physavail),
}
}
return (0);
}
/*
* search for an available phys page,
* copy the old phys page to the new one
* and remap the virt page to the new phys
*/
static int
{
int err;
newppn = find_apage();
CB_VPRINTF((" remap vaddr 0x%p, old 0x%x/0x%x, new 0x%x/0x%x\n",
if (err)
prom_printf("\nmove_page: remap error\n");
return (err);
}
/*
* with the kernel; since we're already running on
* a new stack, the original stack area is skipped
*/
int
cb_relocate(void)
{
str = "cb_relocate";
skip_fmt = " skip vaddr 0x%p, clash=%d, %s\n";
if (is_clash)
clash_cnt++;
else
ok_cnt++;
if (is_ostk)
desc = "orig stack";
else
/*
* page logic:
*
* if (original stack page)
* clash doesn't matter, just skip the page
* else (not original stack page)
* if (no clash)
* setbit to avoid later alloc and overwrite
* else (clash)
* relocate phys page
*/
if (is_ostk) {
} else if (is_clash == 0) {
return (ERR);
}
CB_VPRINTF(("%s: total %d, clash %d, ok %d\n",
/*
* free original stack area for reuse
*/
CB_VPRINTF(("%s: free old stack (0x%lx - 0x%lx)\n",
return (0);
}