rem: if (btop(addr + size) > physmax) size = ptob(physmax - btop(addr));
add: if ((btop(addr + size) - 1) > physmax) size = ptob(physmax - btop(addr) + 1);
context: kphysm_init(	page_t *inpp,	struct memseg *memsegp,	pgcnt_t start,	pgcnt_t npages){	struct memlist	*pmem;	struct memseg	*cur_memseg;	struct memseg	**memsegpp;	pfn_t		base_pfn;	pgcnt_t		num;	pgcnt_t		total_skipped = 0;	pgcnt_t		skipping = 0;	pgcnt_t		pages_done = 0;	pgcnt_t		largepgcnt;	uint64_t	addr;	uint64_t	size;	page_t		*pp = inpp;	int		dobreak = 0;	extern pfn_t	ddiphysmin;	ASSERT(page_hash != NULL && page_hashsz != 0);	for (cur_memseg = memsegp; cur_memseg->pages != NULL; cur_memseg++);	ASSERT(cur_memseg == memsegp || start > 0);	for (pmem = phys_avail; pmem && npages; pmem = pmem->next) {		/*		 * In a 32 bit kernel can't use higher memory if we're		 * not booting in PAE mode. This check takes care of that.		 */		addr = pmem->address;		size = pmem->size;		if (btop(addr) > physmax)			continue;		/*		 * align addr and size - they may not be at page boundaries		 */		if ((addr & MMU_PAGEOFFSET) != 0) {			addr += MMU_PAGEOFFSET;			addr &= ~(uint64_t)MMU_PAGEOFFSET;			size -= addr - pmem->address;		}		/* only process pages below physmax */		if (btop(addr + size) > physmax)			size = ptob(physmax - btop(addr));		num = btop(size);		if (num == 0)			continue;		if (total_skipped < start) {			if (start - total_skipped > num) {				total_skipped += num;				continue;			}			skipping = start - total_skipped;			num -= skipping;			addr += (MMU_PAGESIZE * skipping);			total_skipped = start;		}		if (num == 0)			continue;		if (num > npages)			num = npages;		npages -= num;		pages_done += num;		base_pfn = btop(addr);		/*		 * If the caller didn't provide space for the page		 * structures, carve them out of the memseg they will		 * represent.		 */		if (pp == NULL) {			pgcnt_t pp_pgs;			if (num <= 1)				continue;			/*			 * Compute how many of the pages we need to use for			 * page_ts			 */			pp_pgs = (num * sizeof (page_t)) / MMU_PAGESIZE + 1;			while (mmu_ptob(pp_pgs - 1) / sizeof (page_t) >=			    num - pp_pgs + 1)				--pp_pgs;			PRM_DEBUG(pp_pgs);			pp = vmem_alloc(heap_arena, mmu_ptob(pp_pgs),			    VM_NOSLEEP);			if (pp == NULL) {				cmn_err(CE_WARN, "Unable to add %ld pages to "				    "the system.", num);				continue;			}			hat_devload(kas.a_hat, (void *)pp, mmu_ptob(pp_pgs),			    base_pfn, PROT_READ | PROT_WRITE | HAT_UNORDERED_OK,			    HAT_LOAD | HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST);			bzero(pp, mmu_ptob(pp_pgs));			num -= pp_pgs;			base_pfn += pp_pgs;		}		if (prom_debug)			prom_printf("MEMSEG addr=0x%" PRIx64			    " pgs=0x%lx pfn 0x%lx-0x%lx\n",			    addr, num, base_pfn, base_pfn + num);		/*		 * drop pages below ddiphysmin to simplify ddi memory		 * allocation with non-zero addr_lo requests.		 */		if (base_pfn < ddiphysmin) {			if (base_pfn + num <= ddiphysmin) {				/* drop entire range below ddiphysmin */				continue;			}			/* adjust range to ddiphysmin */			pp += (ddiphysmin - base_pfn);			num -= (ddiphysmin - base_pfn);			base_pfn = ddiphysmin;		}		/*		 * Build the memsegs entry		 */		cur_memseg->pages = pp;		cur_memseg->epages = pp + num;		cur_memseg->pages_base = base_pfn;		cur_memseg->pages_end = base_pfn + num;		/*		 * insert in memseg list in decreasing pfn range order.		 * Low memory is typically more fragmented such that this		 * ordering keeps the larger ranges at the front of the list		 * for code that searches memseg.		 */		memsegpp = &memsegs;		for (;;) {			if (*memsegpp == NULL) {				/* empty memsegs */				memsegs = cur_memseg;				break;			}			/* check for continuity with start of memsegpp */			if (cur_memseg->pages_end == (*memsegpp)->pages_base) {				if (cur_memseg->epages == (*memsegpp)->pages) {					/*					 * contiguous pfn and page_t's. Merge					 * cur_memseg into *memsegpp. Drop					 * cur_memseg					 */					(*memsegpp)->pages_base =					    cur_memseg->pages_base;					(*memsegpp)->pages =					    cur_memseg->pages;					/*					 * check if contiguous with the end of					 * the next memseg.					 */					if ((*memsegpp)->next &&					    ((*memsegpp)->pages_base ==					    (*memsegpp)->next->pages_end)) {						cur_memseg = *memsegpp;						memsegpp = &((*memsegpp)->next);						dobreak = 1;					} else {						break;					}				} else {					/*					 * contiguous pfn but not page_t's.					 * drop last pfn/page_t in cur_memseg					 * to prevent creation of large pages					 * with noncontiguous page_t's if not					 * aligned to largest page boundary.					 */					largepgcnt = page_get_pagecnt(					    page_num_pagesizes() - 1);					if (cur_memseg->pages_end &					    (largepgcnt - 1)) {						num--;						cur_memseg->epages--;						cur_memseg->pages_end--;					}				}			}			/* check for continuity with end of memsegpp */			if (cur_memseg->pages_base == (*memsegpp)->pages_end) {				if (cur_memseg->pages == (*memsegpp)->epages) {					/*					 * contiguous pfn and page_t's. Merge					 * cur_memseg into *memsegpp. Drop					 * cur_memseg.					 */					if (dobreak) {						/* merge previously done */						cur_memseg->pages =						    (*memsegpp)->pages;						cur_memseg->pages_base =						    (*memsegpp)->pages_base;						cur_memseg->next =						    (*memsegpp)->next;					} else {						(*memsegpp)->pages_end =						    cur_memseg->pages_end;						(*memsegpp)->epages =						    cur_memseg->epages;					}					break;				}				/*				 * contiguous pfn but not page_t's.				 * drop first pfn/page_t in cur_memseg				 * to prevent creation of large pages				 * with noncontiguous page_t's if not				 * aligned to largest page boundary.				 */				largepgcnt = page_get_pagecnt(				    page_num_pagesizes() - 1);				if (base_pfn & (largepgcnt - 1)) {					num--;					base_pfn++;					cur_memseg->pages++;					cur_memseg->pages_base++;					pp = cur_memseg->pages;				}				if (dobreak)					break;			}			if (cur_memseg->pages_base >=			    (*memsegpp)->pages_end) {				cur_memseg->next = *memsegpp;				*memsegpp = cur_memseg;				break;			}			if ((*memsegpp)->next == NULL) {				cur_memseg->next = NULL;				(*memsegpp)->next = cur_memseg;				break;			}			memsegpp = &((*memsegpp)->next);			ASSERT(*memsegpp != NULL);		}		/*		 * add_physmem() initializes the PSM part of the page		 * struct by calling the PSM back with add_physmem_cb().		 * In addition it coalesces pages into larger pages as		 * it initializes them.		 */		add_physmem(pp, num, base_pfn);		cur_memseg++;		availrmem_initial += num;		availrmem += num;		/*		 * If the caller provided the page frames to us, then		 * advance in that list.  Otherwise, prepare to allocate		 * our own page frames for the next memseg.		 */		pp = (inpp == NULL) ? NULL : pp + num;	}	PRM_DEBUG(availrmem_initial);	PRM_DEBUG(availrmem);	PRM_DEBUG(freemem);	build_pfn_hash();	return (pages_done);}