17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5986fd29aSsetje * Common Development and Distribution License (the "License").
6986fd29aSsetje * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22986fd29aSsetje * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/saio.h>
287c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
297c478bd9Sstevel@tonic-gate #include <sys/promif.h>
307c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
317c478bd9Sstevel@tonic-gate #include <sys/salib.h>
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #define NIL 0
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate #ifdef DEBUG
367c478bd9Sstevel@tonic-gate static int resalloc_debug = 1;
377c478bd9Sstevel@tonic-gate #else /* DEBUG */
387c478bd9Sstevel@tonic-gate static int resalloc_debug = 0;
397c478bd9Sstevel@tonic-gate #endif /* DEBUG */
407c478bd9Sstevel@tonic-gate #define dprintf if (resalloc_debug) printf
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate extern struct memlist *vfreelistp, *pfreelistp;
437c478bd9Sstevel@tonic-gate extern void reset_alloc(void);
447c478bd9Sstevel@tonic-gate extern void alloc_segment(caddr_t);
457c478bd9Sstevel@tonic-gate
46*a2cd9e18SToomas Soome extern caddr_t memlistpage;
477c478bd9Sstevel@tonic-gate caddr_t le_page;
487c478bd9Sstevel@tonic-gate caddr_t ie_page;
497c478bd9Sstevel@tonic-gate caddr_t scratchmemp;
507c478bd9Sstevel@tonic-gate extern int pagesize;
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #define N_FREELIST 20 /* keep the largest 20 free regions */
537c478bd9Sstevel@tonic-gate static size_t free_size[N_FREELIST];
547c478bd9Sstevel@tonic-gate static caddr_t free_addr[N_FREELIST];
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate * OBP sets up a 1:1 mapping of virtual to physical in the range 8KB-10MB. The
587c478bd9Sstevel@tonic-gate * standalone is free to use any or all of this during its lifetime.
597c478bd9Sstevel@tonic-gate * Unfortunately, some platforms (Serengeti and LW8) can't use the full range.
607c478bd9Sstevel@tonic-gate * See 4799331 for more details. Limited platforms can use up to
617c478bd9Sstevel@tonic-gate * MAPPEDMEM_MINTOP; everyone else can use up to MAPPEDMEM_FULLTOP.
627c478bd9Sstevel@tonic-gate * resalloc_init makes the determination as to how much the machine being booted
637c478bd9Sstevel@tonic-gate * can use.
647c478bd9Sstevel@tonic-gate *
657c478bd9Sstevel@tonic-gate * But wait! There's more! resalloc handles three types of allocations: Two
667c478bd9Sstevel@tonic-gate * flavors of RES_BOOTSCRATCH (RES_BOOTSCRATCH and RES_BOOTSCRATCH_NOFAIL), and
677c478bd9Sstevel@tonic-gate * one of RES_CHILDVIRT. RES_CHILDVIRT is handled by prom_alloc, and is boring.
687c478bd9Sstevel@tonic-gate * We handle RES_BOOTSCRATCH allocations ourselves using the portion of the 1:1
697c478bd9Sstevel@tonic-gate * range not consumed by boot. The unconsumed range is subdivided into two
707c478bd9Sstevel@tonic-gate * portions - the general area from top_resvmem to top_bootmem and the reserved
717c478bd9Sstevel@tonic-gate * area from above memlistpage to top_resvmem. Both RES_BOOTSCRATCH flavors are
727c478bd9Sstevel@tonic-gate * satisfied by the general area until said area is exhausted, at which point
737c478bd9Sstevel@tonic-gate * RES_BOOTSCRATCH allocations return failure. RES_BOOTSCRATCH_NOFAIL
747c478bd9Sstevel@tonic-gate * allocations can't fail, so we'll try to satisfy them from the reserved area
757c478bd9Sstevel@tonic-gate * if the general area is full. If we still can't satisfy the nofail
767c478bd9Sstevel@tonic-gate * allocation, we'll call prom_panic.
777c478bd9Sstevel@tonic-gate *
787c478bd9Sstevel@tonic-gate * This whole boot memory allocation thing needs some serious rethinking.
797c478bd9Sstevel@tonic-gate *
807c478bd9Sstevel@tonic-gate * Memory layout:
817c478bd9Sstevel@tonic-gate *
827c478bd9Sstevel@tonic-gate * |-------| top_bootmem
837c478bd9Sstevel@tonic-gate * | | } MAPPEDMEM_FULLTOP (only on non-serengeti, lw8)
847c478bd9Sstevel@tonic-gate * | | } MAPPEDMEM_MINTOP
857c478bd9Sstevel@tonic-gate * |-------| top_resvmem/scratchmemp
867c478bd9Sstevel@tonic-gate * | | } MAPPEDMEM_RESERVE
877c478bd9Sstevel@tonic-gate * |-------| scratchresvp
887c478bd9Sstevel@tonic-gate * | | } one page
897c478bd9Sstevel@tonic-gate * |-------| memlistpage (at roundup(_end, pagesize))
907c478bd9Sstevel@tonic-gate * |-------| _end
917c478bd9Sstevel@tonic-gate * | boot |
927c478bd9Sstevel@tonic-gate * : :
937c478bd9Sstevel@tonic-gate *
947c478bd9Sstevel@tonic-gate */
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate #define MAPPEDMEM_RESERVE (512*1024) /* reserved for NOFAIL allocs */
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate #define MAPPEDMEM_MINTOP (caddr_t)(6*1024*1024)
997c478bd9Sstevel@tonic-gate #define MAPPEDMEM_FULLTOP (caddr_t)(10*1024*1024)
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate static caddr_t top_bootmem = MAPPEDMEM_MINTOP;
1027c478bd9Sstevel@tonic-gate static caddr_t top_resvmem, scratchresvp;
1037c478bd9Sstevel@tonic-gate
104986fd29aSsetje /*
105986fd29aSsetje * with newboot, boot goes away when it launches the client,
106986fd29aSsetje * so we can safely extend bootmem on sg, and give it back
107986fd29aSsetje * before we die.
108986fd29aSsetje */
109986fd29aSsetje int is_sg;
110986fd29aSsetje caddr_t sg_addr;
111986fd29aSsetje size_t sg_len;
112986fd29aSsetje
1137c478bd9Sstevel@tonic-gate static int
impl_name(char * buf,size_t bufsz)1147c478bd9Sstevel@tonic-gate impl_name(char *buf, size_t bufsz)
1157c478bd9Sstevel@tonic-gate {
116fa9e4066Sahrens pnode_t n = prom_rootnode();
1177c478bd9Sstevel@tonic-gate size_t len = prom_getproplen(n, "name");
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate if (len == 0 || len >= bufsz)
1207c478bd9Sstevel@tonic-gate return (-1);
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate (void) prom_getprop(n, "name", buf);
1237c478bd9Sstevel@tonic-gate buf[len] = '\0';
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate return (0);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate static caddr_t
vpage_from_freelist(size_t bytes)1297c478bd9Sstevel@tonic-gate vpage_from_freelist(size_t bytes)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate caddr_t v;
1327c478bd9Sstevel@tonic-gate int i;
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate /* find first region which fits */
1357c478bd9Sstevel@tonic-gate for (i = 0; i < N_FREELIST && free_size[i] < bytes; i++)
1367c478bd9Sstevel@tonic-gate continue;
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate if (i == N_FREELIST) {
1397c478bd9Sstevel@tonic-gate dprintf("boot: failed to allocate %lu bytes from scratch "
1407c478bd9Sstevel@tonic-gate "memory\n", bytes);
1417c478bd9Sstevel@tonic-gate return (NULL);
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate v = free_addr[i];
1457c478bd9Sstevel@tonic-gate free_addr[i] += bytes;
1467c478bd9Sstevel@tonic-gate free_size[i] -= bytes;
1477c478bd9Sstevel@tonic-gate dprintf("reuse freed temp scratch: bytes = %lu at %p\n", bytes,
1487c478bd9Sstevel@tonic-gate (void *)v);
1497c478bd9Sstevel@tonic-gate return (v);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate * This routine will find the next PAGESIZE chunk in the
1547c478bd9Sstevel@tonic-gate * low MAPPEDMEM_MINTOP. It is analogous to valloc(). It is only for boot
1557c478bd9Sstevel@tonic-gate * scratch memory, because child scratch memory goes up in
1567c478bd9Sstevel@tonic-gate * the the high memory. We just need to verify that the
1577c478bd9Sstevel@tonic-gate * pages are on the list. The calling routine will actually
1587c478bd9Sstevel@tonic-gate * remove them.
1597c478bd9Sstevel@tonic-gate */
1607c478bd9Sstevel@tonic-gate static caddr_t
get_low_vpage(size_t numpages,enum RESOURCES type)1617c478bd9Sstevel@tonic-gate get_low_vpage(size_t numpages, enum RESOURCES type)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate size_t bytes;
1647c478bd9Sstevel@tonic-gate caddr_t v;
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate if (!numpages)
1677c478bd9Sstevel@tonic-gate return (0);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate /* We know the page is mapped because the 1st MAPPEDMEM_MINTOP is 1:1 */
1707c478bd9Sstevel@tonic-gate bytes = numpages * pagesize;
1717c478bd9Sstevel@tonic-gate if (scratchmemp + bytes <= top_bootmem) {
1727c478bd9Sstevel@tonic-gate v = scratchmemp;
1737c478bd9Sstevel@tonic-gate scratchmemp += bytes;
1747c478bd9Sstevel@tonic-gate return (v);
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate /*
1787c478bd9Sstevel@tonic-gate * If we run out of scratch memory, look in the freelist
1797c478bd9Sstevel@tonic-gate */
1807c478bd9Sstevel@tonic-gate if ((v = vpage_from_freelist(bytes)) != NULL)
1817c478bd9Sstevel@tonic-gate return (v);
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate * Try really hard for allocations that can't fail. Look in the area
1857c478bd9Sstevel@tonic-gate * that we've reserved for them.
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate if (type == RES_BOOTSCRATCH_NOFAIL) {
1887c478bd9Sstevel@tonic-gate if (scratchresvp + bytes <= top_resvmem) {
1897c478bd9Sstevel@tonic-gate v = scratchresvp;
1907c478bd9Sstevel@tonic-gate scratchresvp += bytes;
1917c478bd9Sstevel@tonic-gate dprintf("using %lu bytes of reserved mem (%lu left)\n",
1927c478bd9Sstevel@tonic-gate bytes, top_resvmem - scratchresvp);
1937c478bd9Sstevel@tonic-gate return (v);
1947c478bd9Sstevel@tonic-gate } else {
1957c478bd9Sstevel@tonic-gate printf("boot: failed to allocate %lu bytes from "
1967c478bd9Sstevel@tonic-gate "reserved scratch memory\n", bytes);
1977c478bd9Sstevel@tonic-gate prom_panic("boot: scratch memory overflow.\n");
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate return (NULL);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate void
resalloc_init(void)2057c478bd9Sstevel@tonic-gate resalloc_init(void)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate char iarch[128];
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate if (impl_name(iarch, sizeof (iarch)) < 0) {
2107c478bd9Sstevel@tonic-gate dprintf("boot: resalloc_init: failed to read iarch\n");
2117c478bd9Sstevel@tonic-gate return;
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate dprintf("boot: resalloc_init: got iarch %s\n", iarch);
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate * Some versions of SG/LW8 firmware can actually handle the entire 10MB,
2187c478bd9Sstevel@tonic-gate * but we don't have the ability to check for the firmware version here.
2197c478bd9Sstevel@tonic-gate */
2207c478bd9Sstevel@tonic-gate if (strcmp(iarch, "SUNW,Sun-Fire") == 0 ||
221986fd29aSsetje strcmp(iarch, "SUNW,Netra-T12") == 0) {
222986fd29aSsetje is_sg = 1;
223986fd29aSsetje sg_addr = MAPPEDMEM_MINTOP;
224986fd29aSsetje sg_len = MAPPEDMEM_FULLTOP - MAPPEDMEM_MINTOP;
225986fd29aSsetje if (prom_alloc(sg_addr, sg_len, 1) != sg_addr)
226986fd29aSsetje prom_panic("can't extend sg bootmem");
227986fd29aSsetje }
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate top_bootmem = MAPPEDMEM_FULLTOP;
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate dprintf("boot: resalloc_init: boosted top_bootmem to %p\n",
2327c478bd9Sstevel@tonic-gate (void *)top_bootmem);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate caddr_t
resalloc(enum RESOURCES type,size_t bytes,caddr_t virthint,int align)2367c478bd9Sstevel@tonic-gate resalloc(enum RESOURCES type, size_t bytes, caddr_t virthint, int align)
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate caddr_t vaddr;
2397c478bd9Sstevel@tonic-gate long pmap = 0;
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate if (memlistpage == (caddr_t)0)
2427c478bd9Sstevel@tonic-gate reset_alloc();
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate if (bytes == 0)
2457c478bd9Sstevel@tonic-gate return ((caddr_t)0);
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate /* extend request to fill a page */
2487c478bd9Sstevel@tonic-gate bytes = roundup(bytes, pagesize);
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate dprintf("resalloc: bytes = %lu\n", bytes);
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate switch (type) {
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate * even V2 PROMs never bother to indicate whether the
2567c478bd9Sstevel@tonic-gate * first MAPPEDMEM_MINTOP is taken or not. So we do it all here.
2577c478bd9Sstevel@tonic-gate * Smart PROM or no smart PROM.
2587c478bd9Sstevel@tonic-gate */
2597c478bd9Sstevel@tonic-gate case RES_BOOTSCRATCH:
2607c478bd9Sstevel@tonic-gate case RES_BOOTSCRATCH_NOFAIL:
2617c478bd9Sstevel@tonic-gate vaddr = get_low_vpage((bytes/pagesize), type);
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate if (resalloc_debug) {
2647c478bd9Sstevel@tonic-gate dprintf("vaddr = %p, paddr = %lx\n", (void *)vaddr,
2657c478bd9Sstevel@tonic-gate ptob(pmap));
2667c478bd9Sstevel@tonic-gate print_memlist(vfreelistp);
2677c478bd9Sstevel@tonic-gate print_memlist(pfreelistp);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate return (vaddr);
2707c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate case RES_CHILDVIRT:
2737c478bd9Sstevel@tonic-gate vaddr = (caddr_t)prom_alloc(virthint, bytes, align);
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate if (vaddr == (caddr_t)virthint)
2767c478bd9Sstevel@tonic-gate return (vaddr);
2777c478bd9Sstevel@tonic-gate printf("Alloc of 0x%lx bytes at 0x%p refused.\n",
2787c478bd9Sstevel@tonic-gate bytes, (void *)virthint);
2797c478bd9Sstevel@tonic-gate return ((caddr_t)0);
2807c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate default:
2837c478bd9Sstevel@tonic-gate printf("Bad resurce type\n");
2847c478bd9Sstevel@tonic-gate return ((caddr_t)0);
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate #ifdef lint
2897c478bd9Sstevel@tonic-gate static char _end[1]; /* defined by the linker! */
2907c478bd9Sstevel@tonic-gate #endif /* lint */
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate void
reset_alloc(void)2937c478bd9Sstevel@tonic-gate reset_alloc(void)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate extern char _end[];
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate /* Cannot be called multiple times */
2987c478bd9Sstevel@tonic-gate if (memlistpage != (caddr_t)0)
2997c478bd9Sstevel@tonic-gate return;
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate /*
3027c478bd9Sstevel@tonic-gate * Due to kernel history and ease of programming, we
3037c478bd9Sstevel@tonic-gate * want to keep everything private to /boot BELOW MAPPEDMEM_MINTOP.
3047c478bd9Sstevel@tonic-gate * In this way, the kernel can just snarf it all when
3057c478bd9Sstevel@tonic-gate * when it is ready, and not worry about snarfing lists.
3067c478bd9Sstevel@tonic-gate */
3077c478bd9Sstevel@tonic-gate memlistpage = (caddr_t)roundup((uintptr_t)_end, pagesize);
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate /*
3107c478bd9Sstevel@tonic-gate * This next is for scratch memory only
3117c478bd9Sstevel@tonic-gate * We only need 1 page in memlistpage for now
3127c478bd9Sstevel@tonic-gate */
3137c478bd9Sstevel@tonic-gate scratchresvp = (caddr_t)(memlistpage + pagesize);
3147c478bd9Sstevel@tonic-gate scratchmemp = top_resvmem = scratchresvp + MAPPEDMEM_RESERVE;
3157c478bd9Sstevel@tonic-gate le_page = (caddr_t)(scratchmemp + pagesize);
3167c478bd9Sstevel@tonic-gate ie_page = (caddr_t)(le_page + pagesize);
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate bzero(memlistpage, pagesize);
3197c478bd9Sstevel@tonic-gate bzero(scratchmemp, pagesize);
3207c478bd9Sstevel@tonic-gate dprintf("memlistpage = %p\n", (void *)memlistpage);
3217c478bd9Sstevel@tonic-gate dprintf("le_page = %p\n", (void *)le_page);
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate void
resfree(enum RESOURCES type,caddr_t virtaddr,size_t size)3257c478bd9Sstevel@tonic-gate resfree(enum RESOURCES type, caddr_t virtaddr, size_t size)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate int i;
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate /* make sure this is boot scratch memory */
3307c478bd9Sstevel@tonic-gate switch (type) {
3317c478bd9Sstevel@tonic-gate case RES_BOOTSCRATCH:
3327c478bd9Sstevel@tonic-gate if (virtaddr + size > top_bootmem)
3337c478bd9Sstevel@tonic-gate return;
3347c478bd9Sstevel@tonic-gate break;
3357c478bd9Sstevel@tonic-gate default:
3367c478bd9Sstevel@tonic-gate return;
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /*
3407c478bd9Sstevel@tonic-gate * Add this to the end of the free list
3417c478bd9Sstevel@tonic-gate * NOTE: This relies on the fact that KRTLD calls BOP_FREE
3427c478bd9Sstevel@tonic-gate * from largest to smallest chunks.
3437c478bd9Sstevel@tonic-gate */
3447c478bd9Sstevel@tonic-gate for (i = 0; i < N_FREELIST && free_size[i]; i++)
3457c478bd9Sstevel@tonic-gate ;
3467c478bd9Sstevel@tonic-gate if (i == N_FREELIST)
3477c478bd9Sstevel@tonic-gate return;
3487c478bd9Sstevel@tonic-gate free_size[i] = size;
3497c478bd9Sstevel@tonic-gate free_addr[i] = virtaddr;
3507c478bd9Sstevel@tonic-gate }
351