diff options
Diffstat (limited to 'usr/src/uts/i86pc/vm/hat_i86.c')
-rw-r--r-- | usr/src/uts/i86pc/vm/hat_i86.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/usr/src/uts/i86pc/vm/hat_i86.c b/usr/src/uts/i86pc/vm/hat_i86.c index 8da02a4c36..40b033d0e4 100644 --- a/usr/src/uts/i86pc/vm/hat_i86.c +++ b/usr/src/uts/i86pc/vm/hat_i86.c @@ -27,6 +27,7 @@ */ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2012 Joyent, Inc. All rights reserved. */ /* @@ -3350,15 +3351,13 @@ hati_page_unmap(page_t *pp, htable_t *ht, uint_t entry) extern int vpm_enable; /* - * Unload all translations to a page. If the page is a subpage of a large + * Unload translations to a page. If the page is a subpage of a large * page, the large page mappings are also removed. - * - * The forceflags are unused. + * If unloadflag is HAT_CURPROC_PGUNLOAD, then we only unload the translation + * for the current process, otherwise all translations are unloaded. */ - -/*ARGSUSED*/ static int -hati_pageunload(struct page *pp, uint_t pg_szcd, uint_t forceflag) +hati_pageunload(struct page *pp, uint_t pg_szcd, uint_t unloadflag) { page_t *cur_pp = pp; hment_t *hm; @@ -3366,6 +3365,8 @@ hati_pageunload(struct page *pp, uint_t pg_szcd, uint_t forceflag) htable_t *ht; uint_t entry; level_t level; + struct hat *curhat; + ulong_t cnt; XPV_DISALLOW_MIGRATE(); @@ -3375,6 +3376,9 @@ hati_pageunload(struct page *pp, uint_t pg_szcd, uint_t forceflag) ++curthread->t_hatdepth; ASSERT(curthread->t_hatdepth < 16); + if (unloadflag == HAT_CURPROC_PGUNLOAD) + curhat = curthread->t_procp->p_as->a_hat; + #if defined(__amd64) /* * clear the vpm ref. @@ -3387,6 +3391,8 @@ hati_pageunload(struct page *pp, uint_t pg_szcd, uint_t forceflag) * The loop with next_size handles pages with multiple pagesize mappings */ next_size: + if (unloadflag == HAT_CURPROC_PGUNLOAD) + cnt = hat_page_getshare(cur_pp); for (;;) { /* @@ -3398,6 +3404,7 @@ next_size: if (hm == NULL) { x86_hm_exit(cur_pp); +curproc_done: /* * If not part of a larger page, we're done. */ @@ -3424,8 +3431,21 @@ next_size: * If this mapping size matches, remove it. */ level = ht->ht_level; - if (level == pg_szcd) - break; + if (level == pg_szcd) { + if (unloadflag != HAT_CURPROC_PGUNLOAD || + ht->ht_hat == curhat) + break; + /* + * unloadflag == HAT_CURPROC_PGUNLOAD but it's + * not the hat for the current process. Leave + * entry in place. Also do a safety check to + * ensure we don't get in an infinite loop + */ + if (cnt-- == 0) { + x86_hm_exit(cur_pp); + goto curproc_done; + } + } } /* @@ -3435,14 +3455,18 @@ next_size: hm = hati_page_unmap(cur_pp, ht, entry); if (hm != NULL) hment_free(hm); + + /* Perform check above for being part of a larger page. */ + if (unloadflag == HAT_CURPROC_PGUNLOAD) + goto curproc_done; } } int -hat_pageunload(struct page *pp, uint_t forceflag) +hat_pageunload(struct page *pp, uint_t unloadflag) { ASSERT(PAGE_EXCL(pp)); - return (hati_pageunload(pp, 0, forceflag)); + return (hati_pageunload(pp, 0, unloadflag)); } /* |