diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/xen/io/xnb.c | 6 | ||||
-rw-r--r-- | usr/src/uts/i86pc/vm/hat_i86.c | 1 | ||||
-rw-r--r-- | usr/src/uts/i86pc/vm/vm_dep.h | 1 | ||||
-rw-r--r-- | usr/src/uts/i86pc/vm/vm_machdep.c | 42 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/os/balloon.c | 100 |
5 files changed, 81 insertions, 69 deletions
diff --git a/usr/src/uts/common/xen/io/xnb.c b/usr/src/uts/common/xen/io/xnb.c index 95a05680c9..b13a9354c2 100644 --- a/usr/src/uts/common/xen/io/xnb.c +++ b/usr/src/uts/common/xen/io/xnb.c @@ -48,6 +48,7 @@ #include <sys/balloon_impl.h> #include <sys/evtchn_impl.h> #include <sys/gnttab.h> +#include <vm/vm_dep.h> #include <sys/gld.h> #include <inet/ip.h> @@ -506,6 +507,11 @@ static void xnb_free_page(xnb_t *xnbp, mfn_t mfn) { int r; + pfn_t pfn; + + pfn = xen_assign_pfn(mfn); + pfnzero(pfn, 0, PAGESIZE); + xen_release_pfn(pfn); /* * This happens only in the error path, so batching is diff --git a/usr/src/uts/i86pc/vm/hat_i86.c b/usr/src/uts/i86pc/vm/hat_i86.c index dd07dc59f4..490c010a31 100644 --- a/usr/src/uts/i86pc/vm/hat_i86.c +++ b/usr/src/uts/i86pc/vm/hat_i86.c @@ -4143,6 +4143,7 @@ hat_kpm_pfn2va(pfn_t pfn) { uintptr_t vaddr = (uintptr_t)kpm_vbase + mmu_ptob(pfn); + ASSERT(!pfn_is_foreign(pfn)); return ((caddr_t)vaddr); } diff --git a/usr/src/uts/i86pc/vm/vm_dep.h b/usr/src/uts/i86pc/vm/vm_dep.h index e6abe4203b..43bbd19d6a 100644 --- a/usr/src/uts/i86pc/vm/vm_dep.h +++ b/usr/src/uts/i86pc/vm/vm_dep.h @@ -512,6 +512,7 @@ extern page_t *page_freelist_split(uchar_t, extern page_t *page_freelist_coalesce(int, uchar_t, uint_t, uint_t, int, pfn_t); extern uint_t page_get_pagecolors(uint_t); +extern void pfnzero(pfn_t, uint_t, uint_t); #ifdef __cplusplus } diff --git a/usr/src/uts/i86pc/vm/vm_machdep.c b/usr/src/uts/i86pc/vm/vm_machdep.c index e48098ec4c..b97f459245 100644 --- a/usr/src/uts/i86pc/vm/vm_machdep.c +++ b/usr/src/uts/i86pc/vm/vm_machdep.c @@ -3288,28 +3288,34 @@ faulted: return (ret); } +void +pagezero(page_t *pp, uint_t off, uint_t len) +{ + ASSERT(PAGE_LOCKED(pp)); + pfnzero(page_pptonum(pp), off, len); +} + /* - * Zero the physical page from off to off + len given by `pp' + * Zero the physical page from off to off + len given by pfn * without changing the reference and modified bits of page. * * We use this using CPU private page address #2, see ppcopy() for more info. - * pagezero() must not be called at interrupt level. + * pfnzero() must not be called at interrupt level. */ void -pagezero(page_t *pp, uint_t off, uint_t len) +pfnzero(pfn_t pfn, uint_t off, uint_t len) { caddr_t pp_addr2; hat_mempte_t pte2; - kmutex_t *ppaddr_mutex; + kmutex_t *ppaddr_mutex = NULL; ASSERT_STACK_ALIGNED(); ASSERT(len <= MMU_PAGESIZE); ASSERT(off <= MMU_PAGESIZE); ASSERT(off + len <= MMU_PAGESIZE); - ASSERT(PAGE_LOCKED(pp)); - if (kpm_enable) { - pp_addr2 = hat_kpm_page2va(pp, 0); + if (kpm_enable && !pfn_is_foreign(pfn)) { + pp_addr2 = hat_kpm_pfn2va(pfn); kpreempt_disable(); } else { kpreempt_disable(); @@ -3320,7 +3326,7 @@ pagezero(page_t *pp, uint_t off, uint_t len) ppaddr_mutex = &CPU->cpu_ppaddr_mutex; mutex_enter(ppaddr_mutex); - hat_mempte_remap(page_pptonum(pp), pp_addr2, pte2, + hat_mempte_remap(pfn, pp_addr2, pte2, PROT_READ | PROT_WRITE | HAT_STORECACHING_OK, HAT_LOAD_NOCONSIST); } @@ -3359,18 +3365,20 @@ pagezero(page_t *pp, uint_t off, uint_t len) bzero(pp_addr2 + off, len); } + if (!kpm_enable || pfn_is_foreign(pfn)) { #ifdef __xpv - /* - * On the hypervisor this page might get used for a page table before - * any intervening change to this mapping, so blow it away. - */ - if (!kpm_enable && HYPERVISOR_update_va_mapping((uintptr_t)pp_addr2, 0, - UVMF_INVLPG) < 0) - panic("HYPERVISOR_update_va_mapping() failed"); + /* + * On the hypervisor this page might get used for a page + * table before any intervening change to this mapping, + * so blow it away. + */ + if (HYPERVISOR_update_va_mapping((uintptr_t)pp_addr2, 0, + UVMF_INVLPG) < 0) + panic("HYPERVISOR_update_va_mapping() failed"); #endif - - if (!kpm_enable) mutex_exit(ppaddr_mutex); + } + kpreempt_enable(); } diff --git a/usr/src/uts/i86xpv/os/balloon.c b/usr/src/uts/i86xpv/os/balloon.c index 3866acf364..b5a3057a6d 100644 --- a/usr/src/uts/i86xpv/os/balloon.c +++ b/usr/src/uts/i86xpv/os/balloon.c @@ -79,9 +79,6 @@ static page_t *bln_spare_list_front, *bln_spare_list_back; int balloon_zero_memory = 1; size_t balloon_minkmem = (8 * 1024 * 1024); -static caddr_t balloon_kva; -static kmutex_t balloon_kva_mutex; -static void balloon_zero_page(pfn_t pfn); /* * reassign_pfn() calls update_contig_pfnlist(), which can cause a large @@ -385,6 +382,9 @@ balloon_inc_reservation(ulong_t credit) page_t *pp; page_t *new_list_front, *new_list_back; + /* Make sure we're single-threaded. */ + ASSERT(MUTEX_HELD(&bln_mutex)); + rv = 0; new_list_front = new_list_back = NULL; meta_pg_start = meta_pg_end = 0; @@ -434,22 +434,36 @@ balloon_inc_reservation(ulong_t credit) } cnt = i; locked = balloon_lock_contig_pfnlist(cnt); - for (i = 0, pp = new_list_front; (i < meta_pg_start) && (pp != NULL); + for (i = 0, pp = new_list_front; i < meta_pg_start; i++, pp = pp->p_next) { reassign_pfn(pp->p_pagenum, mfn_frames[i]); } - for (i = meta_pg_end; (i < cnt) && (pp != NULL); i++, pp = pp->p_next) { + for (i = meta_pg_end; i < cnt; i++, pp = pp->p_next) { reassign_pfn(pp->p_pagenum, mfn_frames[i]); } if (locked) unlock_contig_pfnlist(); + + /* + * Make sure we don't allow pages without pfn->mfn mappings + * into the system. + */ + ASSERT(pp == NULL); + while (new_list_front != NULL) { pp = new_list_front; new_list_front = pp->p_next; page_free(pp, 1); } - page_unresv(cnt - (meta_pg_end - meta_pg_start)); + /* + * Variable review: at this point, rv contains the number of pages + * the hypervisor gave us. cnt contains the number of pages for which + * we had page_t structures. i contains the number of pages + * where we set up pfn <-> mfn mappings. If this ASSERT trips, that + * means we somehow lost page_t's from our local list. + */ + ASSERT(cnt == i); if (cnt < rv) { /* * We couldn't get page structures. @@ -457,17 +471,21 @@ balloon_inc_reservation(ulong_t credit) * This shouldn't happen, but causes no real harm if it does. * On debug kernels, we'll flag it. On all kernels, we'll * give back the pages we couldn't assign. + * + * Since these pages are new to the system and haven't been + * used, we don't bother zeroing them. */ #ifdef DEBUG - cmn_err(CE_WARN, "Could only assign %d of %ld pages", i, rv); + cmn_err(CE_WARN, "Could only assign %d of %ld pages", cnt, rv); #endif /* DEBUG */ - (void) balloon_free_pages(rv - i, &mfn_frames[i], NULL, NULL); + (void) balloon_free_pages(rv - cnt, &mfn_frames[i], NULL, NULL); - rv = i; + rv = cnt; } xen_allow_migrate(); + page_unresv(rv - (meta_pg_end - meta_pg_start)); return (rv); } @@ -481,6 +499,7 @@ balloon_dec_reservation(ulong_t debit) { int i, locked; long rv; + ulong_t request; page_t *pp; bzero(mfn_frames, sizeof (mfn_frames)); @@ -489,6 +508,7 @@ balloon_dec_reservation(ulong_t debit) if (debit > FRAME_ARRAY_SIZE) { debit = FRAME_ARRAY_SIZE; } + request = debit; /* * Don't bother if there isn't a safe amount of kmem left. @@ -499,7 +519,7 @@ balloon_dec_reservation(ulong_t debit) return (0); } - if (page_resv(debit, KM_NOSLEEP) == 0) { + if (page_resv(request, KM_NOSLEEP) == 0) { return (0); } xen_block_migrate(); @@ -528,10 +548,21 @@ balloon_dec_reservation(ulong_t debit) } if (debit == 0) { xen_allow_migrate(); + page_unresv(request); return (0); } /* + * We zero all the pages before we start reassigning them in order to + * minimize the time spent holding the lock on the contig pfn list. + */ + if (balloon_zero_memory) { + for (i = 0; i < debit; i++) { + pfnzero(pfn_frames[i], 0, PAGESIZE); + } + } + + /* * Remove all mappings for the pfns from the system */ locked = balloon_lock_contig_pfnlist(debit); @@ -553,6 +584,8 @@ balloon_dec_reservation(ulong_t debit) } xen_allow_migrate(); + if (debit != request) + page_unresv(request - debit); return (rv); } @@ -719,10 +752,6 @@ balloon_init(pgcnt_t nr_pages) bln_stats.bln_max_pages = nr_pages; cv_init(&bln_cv, NULL, CV_DEFAULT, NULL); - /* init balloon zero logic */ - balloon_kva = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP); - mutex_init(&balloon_kva_mutex, NULL, MUTEX_DRIVER, NULL); - bln_stats.bln_hard_limit = (spgcnt_t)HYPERVISOR_memory_op( XENMEM_maximum_reservation, &domid); @@ -774,9 +803,10 @@ balloon_alloc_pages(uint_t page_cnt, mfn_t *mfns) /* * balloon_free_pages() * free page_cnt pages, using any combination of mfns, pfns, and kva as long - * as they refer to the same mapping. We need to zero the pages before - * giving them back to the hypervisor. kva space is not free'd up in case - * the caller wants to re-use it. + * as they refer to the same mapping. If an array of mfns is passed in, we + * assume they were already cleared. Otherwise, we need to zero the pages + * before giving them back to the hypervisor. kva space is not free'd up in + * case the caller wants to re-use it. */ long balloon_free_pages(uint_t page_cnt, mfn_t *mfns, caddr_t kva, pfn_t *pfns) @@ -831,7 +861,7 @@ balloon_free_pages(uint_t page_cnt, mfn_t *mfns, caddr_t kva, pfn_t *pfns) * need to do this *before* we give back the MFN */ if ((kva == NULL) && (balloon_zero_memory)) { - balloon_zero_page(pfn); + pfnzero(pfn, 0, PAGESIZE); } /* @@ -870,18 +900,6 @@ balloon_free_pages(uint_t page_cnt, mfn_t *mfns, caddr_t kva, pfn_t *pfns) } } } - - /* - * if all we were given was an array of MFN's, we only need to zero out - * each page. The MFNs will be free'd up below. - */ - } else if (balloon_zero_memory) { - ASSERT(mfns != NULL); - for (i = 0; i < page_cnt; i++) { - pfn = xen_assign_pfn(mfns[i]); - balloon_zero_page(pfn); - xen_release_pfn(pfn); - } } /* @@ -1020,28 +1038,6 @@ balloon_replace_pages(uint_t nextents, page_t **pp, uint_t addr_bits, /* - * balloon_zero_page() - * zero out the page. - */ -static void -balloon_zero_page(pfn_t pfn) -{ - /* balloon_init() should have been called first */ - ASSERT(balloon_kva != NULL); - - mutex_enter(&balloon_kva_mutex); - - /* map the pfn into kva, zero the page, then unmap the pfn */ - hat_devload(kas.a_hat, balloon_kva, PAGESIZE, pfn, - HAT_STORECACHING_OK | PROT_READ | PROT_WRITE | HAT_NOSYNC, - HAT_LOAD_LOCK); - bzero(balloon_kva, PAGESIZE); - hat_unload(kas.a_hat, balloon_kva, PAGESIZE, HAT_UNLOAD); - - mutex_exit(&balloon_kva_mutex); -} - -/* * Called from the driver - return the requested stat. */ size_t |