xref: /illumos-gate/usr/src/uts/i86pc/vm/hat_kdi.c (revision 86ef0a63)
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
5ae115bc7Smrj  * Common Development and Distribution License (the "License").
6ae115bc7Smrj  * 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  */
217aec1d6eScindi 
227c478bd9Sstevel@tonic-gate /*
23ae115bc7Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*74ecdb51SJohn Levon  *
26*74ecdb51SJohn Levon  * Copyright 2018 Joyent, Inc.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * HAT interfaces used by the kernel debugger to interact with the VM system.
317c478bd9Sstevel@tonic-gate  * These interfaces are invoked when the world is stopped.  As such, no blocking
327c478bd9Sstevel@tonic-gate  * operations may be performed.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357aec1d6eScindi #include <sys/cpuvar.h>
367c478bd9Sstevel@tonic-gate #include <sys/kdi_impl.h>
377c478bd9Sstevel@tonic-gate #include <sys/errno.h>
387c478bd9Sstevel@tonic-gate #include <sys/systm.h>
397c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
407c478bd9Sstevel@tonic-gate #include <sys/mman.h>
417c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
427c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
437c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
447c478bd9Sstevel@tonic-gate #include <vm/hat_i86.h>
45843e1988Sjohnlev #if defined(__xpv)
46843e1988Sjohnlev #include <sys/hypervisor.h>
47843e1988Sjohnlev #endif
48ae115bc7Smrj #include <sys/bootinfo.h>
49ae115bc7Smrj #include <vm/kboot_mmu.h>
507c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * The debugger needs direct access to the PTE of one page table entry
547c478bd9Sstevel@tonic-gate  * in order to implement vtop and physical read/writes
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate static uintptr_t hat_kdi_page = 0;	/* vaddr for phsical page accesses */
57ae115bc7Smrj static uint_t use_kbm = 1;
587c478bd9Sstevel@tonic-gate uint_t hat_kdi_use_pae;			/* if 0, use x86pte32_t for pte type */
597c478bd9Sstevel@tonic-gate 
60843e1988Sjohnlev #if !defined(__xpv)
61843e1988Sjohnlev static x86pte_t *hat_kdi_pte = NULL;	/* vaddr of pte for hat_kdi_page */
62843e1988Sjohnlev #endif
63843e1988Sjohnlev 
647c478bd9Sstevel@tonic-gate /*
65ae115bc7Smrj  * Get the address for remapping physical pages during boot
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate void
hat_boot_kdi_init(void)687c478bd9Sstevel@tonic-gate hat_boot_kdi_init(void)
697c478bd9Sstevel@tonic-gate {
70ae115bc7Smrj 	hat_kdi_page = (uintptr_t)kbm_push(0);	/* first call gets address... */
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate  * Switch to using a page in the kernel's va range for physical memory access.
757c478bd9Sstevel@tonic-gate  * We need to allocate a virtual page, then permanently map in the page that
767c478bd9Sstevel@tonic-gate  * contains the PTE to it.
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate void
hat_kdi_init(void)797c478bd9Sstevel@tonic-gate hat_kdi_init(void)
807c478bd9Sstevel@tonic-gate {
81ae115bc7Smrj 	/*LINTED:set but not used in function*/
828f33f62fSToomas Soome 	htable_t *ht __unused;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	/*
857c478bd9Sstevel@tonic-gate 	 * Get an kernel page VA to use for phys mem access. Then make sure
867c478bd9Sstevel@tonic-gate 	 * the VA has a page table.
877c478bd9Sstevel@tonic-gate 	 */
887c478bd9Sstevel@tonic-gate 	hat_kdi_use_pae = mmu.pae_hat;
897c478bd9Sstevel@tonic-gate 	hat_kdi_page = (uintptr_t)vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
907c478bd9Sstevel@tonic-gate 	ht = htable_create(kas.a_hat, hat_kdi_page, 0, NULL);
91ae115bc7Smrj 	use_kbm = 0;
927c478bd9Sstevel@tonic-gate 
93843e1988Sjohnlev #ifndef __xpv
947c478bd9Sstevel@tonic-gate 	/*
957c478bd9Sstevel@tonic-gate 	 * Get an address at which to put the pagetable and devload it.
967c478bd9Sstevel@tonic-gate 	 */
977c478bd9Sstevel@tonic-gate 	hat_kdi_pte = vmem_xalloc(heap_arena, MMU_PAGESIZE, MMU_PAGESIZE, 0,
987c478bd9Sstevel@tonic-gate 	    0, NULL, NULL, VM_SLEEP);
997c478bd9Sstevel@tonic-gate 	hat_devload(kas.a_hat, (caddr_t)hat_kdi_pte, MMU_PAGESIZE, ht->ht_pfn,
1007c478bd9Sstevel@tonic-gate 	    PROT_READ | PROT_WRITE | HAT_NOSYNC | HAT_UNORDERED_OK,
1017c478bd9Sstevel@tonic-gate 	    HAT_LOAD | HAT_LOAD_NOCONSIST);
102ae115bc7Smrj 	hat_kdi_pte =
103ae115bc7Smrj 	    PT_INDEX_PTR(hat_kdi_pte, htable_va2entry(hat_kdi_page, ht));
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	HTABLE_INC(ht->ht_valid_cnt);
1067c478bd9Sstevel@tonic-gate 	htable_release(ht);
107843e1988Sjohnlev #endif
108843e1988Sjohnlev }
109843e1988Sjohnlev 
110843e1988Sjohnlev #ifdef __xpv
111843e1988Sjohnlev 
112843e1988Sjohnlev /*
113843e1988Sjohnlev  * translate machine address to physical address
114843e1988Sjohnlev  */
115843e1988Sjohnlev static uint64_t
kdi_ptom(uint64_t pa)116843e1988Sjohnlev kdi_ptom(uint64_t pa)
117843e1988Sjohnlev {
118843e1988Sjohnlev 	extern pfn_t *mfn_list;
119843e1988Sjohnlev 	ulong_t mfn = mfn_list[mmu_btop(pa)];
120843e1988Sjohnlev 
121843e1988Sjohnlev 	return (pfn_to_pa(mfn) | (pa & MMU_PAGEOFFSET));
1227c478bd9Sstevel@tonic-gate }
123843e1988Sjohnlev 
124843e1988Sjohnlev /*
125843e1988Sjohnlev  * This is like mfn_to_pfn(), but we can't use ontrap() from kmdb.
126843e1988Sjohnlev  * Instead we let the fault happen and kmdb deals with it.
127843e1988Sjohnlev  */
128843e1988Sjohnlev static uint64_t
kdi_mtop(uint64_t ma)129843e1988Sjohnlev kdi_mtop(uint64_t ma)
130843e1988Sjohnlev {
131843e1988Sjohnlev 	pfn_t pfn;
132843e1988Sjohnlev 	mfn_t mfn = ma >> MMU_PAGESHIFT;
133843e1988Sjohnlev 
134843e1988Sjohnlev 	if (HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL) < mfn)
135843e1988Sjohnlev 		return (ma | PFN_IS_FOREIGN_MFN);
136843e1988Sjohnlev 
137843e1988Sjohnlev 	pfn = mfn_to_pfn_mapping[mfn];
138843e1988Sjohnlev 	if (pfn >= mfn_count || pfn_to_mfn(pfn) != mfn)
139843e1988Sjohnlev 		return (ma | PFN_IS_FOREIGN_MFN);
140843e1988Sjohnlev 	return (pfn_to_pa(pfn) | (ma & MMU_PAGEOFFSET));
141843e1988Sjohnlev }
142843e1988Sjohnlev 
143843e1988Sjohnlev #else
144ae115bc7Smrj #define	kdi_mtop(m)	(m)
145ae115bc7Smrj #define	kdi_ptom(p)	(p)
146843e1988Sjohnlev #endif
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1497c478bd9Sstevel@tonic-gate int
kdi_vtop(uintptr_t va,uint64_t * pap)1507c478bd9Sstevel@tonic-gate kdi_vtop(uintptr_t va, uint64_t *pap)
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate 	uintptr_t vaddr = va;
1537c478bd9Sstevel@tonic-gate 	size_t	len;
1547c478bd9Sstevel@tonic-gate 	pfn_t	pfn;
1557c478bd9Sstevel@tonic-gate 	uint_t	prot;
1567c478bd9Sstevel@tonic-gate 	int	level;
1577c478bd9Sstevel@tonic-gate 	x86pte_t pte;
1587c478bd9Sstevel@tonic-gate 	int	index;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	/*
1617c478bd9Sstevel@tonic-gate 	 * if the mmu struct isn't relevant yet, we need to probe
1627c478bd9Sstevel@tonic-gate 	 * the boot loader's pagetables.
1637c478bd9Sstevel@tonic-gate 	 */
1647c478bd9Sstevel@tonic-gate 	if (!khat_running) {
165ae115bc7Smrj 		if (kbm_probe(&vaddr, &len, &pfn, &prot) == 0)
1667c478bd9Sstevel@tonic-gate 			return (ENOENT);
1677c478bd9Sstevel@tonic-gate 		if (vaddr > va)
1687c478bd9Sstevel@tonic-gate 			return (ENOENT);
1697c478bd9Sstevel@tonic-gate 		if (vaddr < va)
1707c478bd9Sstevel@tonic-gate 			pfn += mmu_btop(va - vaddr);
171ae115bc7Smrj 		*pap = pfn_to_pa(pfn) + (vaddr & MMU_PAGEOFFSET);
1727c478bd9Sstevel@tonic-gate 		return (0);
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 * We can't go through normal hat routines, so we'll use
1777c478bd9Sstevel@tonic-gate 	 * kdi_pread() to walk the page tables
1787c478bd9Sstevel@tonic-gate 	 */
179843e1988Sjohnlev #if defined(__xpv)
180843e1988Sjohnlev 	*pap = pfn_to_pa(CPU->cpu_current_hat->hat_htable->ht_pfn);
181843e1988Sjohnlev #else
182*74ecdb51SJohn Levon 	*pap = getcr3_pa();
183843e1988Sjohnlev #endif
1847c478bd9Sstevel@tonic-gate 	for (level = mmu.max_level; ; --level) {
1857c478bd9Sstevel@tonic-gate 		index = (va >> LEVEL_SHIFT(level)) & (mmu.ptes_per_table - 1);
1867c478bd9Sstevel@tonic-gate 		*pap += index << mmu.pte_size_shift;
1877c478bd9Sstevel@tonic-gate 		pte = 0;
1887c478bd9Sstevel@tonic-gate 		if (kdi_pread((caddr_t)&pte, mmu.pte_size, *pap, &len) != 0)
1897c478bd9Sstevel@tonic-gate 			return (ENOENT);
1907c478bd9Sstevel@tonic-gate 		if (pte == 0)
1917c478bd9Sstevel@tonic-gate 			return (ENOENT);
1927c478bd9Sstevel@tonic-gate 		if (level > 0 && level <= mmu.max_page_level &&
1937c478bd9Sstevel@tonic-gate 		    (pte & PT_PAGESIZE)) {
194ae115bc7Smrj 			*pap = kdi_mtop(pte & PT_PADDR_LGPG);
1957c478bd9Sstevel@tonic-gate 			break;
1967c478bd9Sstevel@tonic-gate 		} else {
197ae115bc7Smrj 			*pap = kdi_mtop(pte & PT_PADDR);
1987c478bd9Sstevel@tonic-gate 			if (level == 0)
1997c478bd9Sstevel@tonic-gate 				break;
2007c478bd9Sstevel@tonic-gate 		}
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	*pap += va & LEVEL_OFFSET(level);
2037c478bd9Sstevel@tonic-gate 	return (0);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate static int
kdi_prw(caddr_t buf,size_t nbytes,uint64_t pa,size_t * ncopiedp,int doread)2077c478bd9Sstevel@tonic-gate kdi_prw(caddr_t buf, size_t nbytes, uint64_t pa, size_t *ncopiedp, int doread)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate 	size_t	ncopied = 0;
2107c478bd9Sstevel@tonic-gate 	off_t	pgoff;
2117c478bd9Sstevel@tonic-gate 	size_t	sz;
2127c478bd9Sstevel@tonic-gate 	caddr_t	va;
2137c478bd9Sstevel@tonic-gate 	caddr_t	from;
2147c478bd9Sstevel@tonic-gate 	caddr_t	to;
2157c478bd9Sstevel@tonic-gate 	x86pte_t pte;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	/*
2187c478bd9Sstevel@tonic-gate 	 * if this is called before any initialization - fail
2197c478bd9Sstevel@tonic-gate 	 */
2207c478bd9Sstevel@tonic-gate 	if (hat_kdi_page == 0)
2217c478bd9Sstevel@tonic-gate 		return (EAGAIN);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	while (nbytes > 0) {
2247c478bd9Sstevel@tonic-gate 		/*
2257c478bd9Sstevel@tonic-gate 		 * figure out the addresses and construct a minimal PTE
2267c478bd9Sstevel@tonic-gate 		 */
2277c478bd9Sstevel@tonic-gate 		pgoff = pa & MMU_PAGEOFFSET;
2287c478bd9Sstevel@tonic-gate 		sz = MIN(nbytes, MMU_PAGESIZE - pgoff);
2297c478bd9Sstevel@tonic-gate 		va = (caddr_t)hat_kdi_page + pgoff;
230843e1988Sjohnlev 		pte = kdi_ptom(mmu_ptob(mmu_btop(pa))) | PT_VALID;
2317c478bd9Sstevel@tonic-gate 		if (doread) {
2327c478bd9Sstevel@tonic-gate 			from = va;
2337c478bd9Sstevel@tonic-gate 			to = buf;
2347c478bd9Sstevel@tonic-gate 		} else {
2357c478bd9Sstevel@tonic-gate 			PTE_SET(pte, PT_WRITABLE);
2367c478bd9Sstevel@tonic-gate 			from = buf;
2377c478bd9Sstevel@tonic-gate 			to = va;
2387c478bd9Sstevel@tonic-gate 		}
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 		/*
2417c478bd9Sstevel@tonic-gate 		 * map the physical page
2427c478bd9Sstevel@tonic-gate 		 */
243ae115bc7Smrj 		if (use_kbm)
244ae115bc7Smrj 			(void) kbm_push(pa);
245843e1988Sjohnlev #if defined(__xpv)
246843e1988Sjohnlev 		else
247843e1988Sjohnlev 			(void) HYPERVISOR_update_va_mapping(
248843e1988Sjohnlev 			    (uintptr_t)va, pte, UVMF_INVLPG);
249843e1988Sjohnlev #else
2507c478bd9Sstevel@tonic-gate 		else if (hat_kdi_use_pae)
2517c478bd9Sstevel@tonic-gate 			*hat_kdi_pte = pte;
2527c478bd9Sstevel@tonic-gate 		else
2537c478bd9Sstevel@tonic-gate 			*(x86pte32_t *)hat_kdi_pte = pte;
254*74ecdb51SJohn Levon 		mmu_flush_tlb_kpage(hat_kdi_page);
255843e1988Sjohnlev #endif
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 		bcopy(from, to, sz);
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 		/*
2607c478bd9Sstevel@tonic-gate 		 * erase the mapping
2617c478bd9Sstevel@tonic-gate 		 */
262ae115bc7Smrj 		if (use_kbm)
263ae115bc7Smrj 			kbm_pop();
264843e1988Sjohnlev #if defined(__xpv)
265843e1988Sjohnlev 		else
266843e1988Sjohnlev 			(void) HYPERVISOR_update_va_mapping(
267843e1988Sjohnlev 			    (uintptr_t)va, 0, UVMF_INVLPG);
268843e1988Sjohnlev #else
2697c478bd9Sstevel@tonic-gate 		else if (hat_kdi_use_pae)
2707c478bd9Sstevel@tonic-gate 			*hat_kdi_pte = 0;
2717c478bd9Sstevel@tonic-gate 		else
2727c478bd9Sstevel@tonic-gate 			*(x86pte32_t *)hat_kdi_pte = 0;
273*74ecdb51SJohn Levon 		mmu_flush_tlb_kpage(hat_kdi_page);
274843e1988Sjohnlev #endif
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 		buf += sz;
2777c478bd9Sstevel@tonic-gate 		pa += sz;
2787c478bd9Sstevel@tonic-gate 		nbytes -= sz;
2797c478bd9Sstevel@tonic-gate 		ncopied += sz;
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if (ncopied == 0)
2837c478bd9Sstevel@tonic-gate 		return (ENOENT);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	*ncopiedp = ncopied;
2867c478bd9Sstevel@tonic-gate 	return (0);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate int
kdi_pread(caddr_t buf,size_t nbytes,uint64_t addr,size_t * ncopiedp)2907c478bd9Sstevel@tonic-gate kdi_pread(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 	return (kdi_prw(buf, nbytes, addr, ncopiedp, 1));
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate int
kdi_pwrite(caddr_t buf,size_t nbytes,uint64_t addr,size_t * ncopiedp)2967c478bd9Sstevel@tonic-gate kdi_pwrite(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp)
2977c478bd9Sstevel@tonic-gate {
2987c478bd9Sstevel@tonic-gate 	return (kdi_prw(buf, nbytes, addr, ncopiedp, 0));
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate 
301*74ecdb51SJohn Levon #if !defined(__xpv)
302*74ecdb51SJohn Levon /*
303*74ecdb51SJohn Levon  * This gets used for flushing the TLB on all the slaves just prior to doing a
304*74ecdb51SJohn Levon  * kdi_prw().  It's unclear why this was originally done, since kdi_prw() itself
305*74ecdb51SJohn Levon  * will flush any lingering hat_kdi_page mappings, but let's presume it was a
306*74ecdb51SJohn Levon  * good idea.
307*74ecdb51SJohn Levon  */
308*74ecdb51SJohn Levon void
kdi_flush_caches(void)309*74ecdb51SJohn Levon kdi_flush_caches(void)
310*74ecdb51SJohn Levon {
311*74ecdb51SJohn Levon 	mmu_flush_tlb(FLUSH_TLB_ALL, NULL);
312*74ecdb51SJohn Levon }
313*74ecdb51SJohn Levon #endif
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate /*
3167c478bd9Sstevel@tonic-gate  * Return the number of bytes, relative to the beginning of a given range, that
3177c478bd9Sstevel@tonic-gate  * are non-toxic (can be read from and written to with relative impunity).
3187c478bd9Sstevel@tonic-gate  */
3197c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3207c478bd9Sstevel@tonic-gate size_t
kdi_range_is_nontoxic(uintptr_t va,size_t sz,int write)3217c478bd9Sstevel@tonic-gate kdi_range_is_nontoxic(uintptr_t va, size_t sz, int write)
3227c478bd9Sstevel@tonic-gate {
3237c478bd9Sstevel@tonic-gate 	extern uintptr_t toxic_addr;
3247c478bd9Sstevel@tonic-gate 	extern size_t	toxic_size;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/*
3277c478bd9Sstevel@tonic-gate 	 * Check 64 bit toxic range.
3287c478bd9Sstevel@tonic-gate 	 */
3297c478bd9Sstevel@tonic-gate 	if (toxic_addr != 0 &&
3307c478bd9Sstevel@tonic-gate 	    va + sz >= toxic_addr &&
3317c478bd9Sstevel@tonic-gate 	    va < toxic_addr + toxic_size)
3327c478bd9Sstevel@tonic-gate 		return (va < toxic_addr ? toxic_addr - va : 0);
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	/*
3357c478bd9Sstevel@tonic-gate 	 * avoid any Virtual Address hole
3367c478bd9Sstevel@tonic-gate 	 */
3377c478bd9Sstevel@tonic-gate 	if (va + sz >= hole_start && va < hole_end)
3387c478bd9Sstevel@tonic-gate 		return (va < hole_start ? hole_start - va : 0);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	return (sz);
3417c478bd9Sstevel@tonic-gate }
342