Print this page
NEX-19598 HAT panic
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-16970 assertion failed: ht->ht_valid_cnt >= 0, file: ../../i86pc/vm/htable.c, line: 1204
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-18463 Parallel dump produces corrupted dump file
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-5164 backport illumos 6514 AS_* lock macros simplification
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
6514 AS_* lock macros simplification
Reviewed by: Piotr Jasiukajtis <estibi@me.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Albert Lee <trisk@omniti.com>
Approved by: Dan McDonald <danmcd@omniti.com>

@@ -24,11 +24,12 @@
 /*
  * Copyright (c) 2010, Intel Corporation.
  * All rights reserved.
  */
 /*
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.  All rights reserved.
  * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
  */
 
 /*
  * VM - Hardware Address Translation management for i386 and amd64

@@ -263,10 +264,11 @@
         ASSERT(AS_WRITE_HELD(as));
         hat = kmem_cache_alloc(hat_cache, KM_SLEEP);
         hat->hat_as = as;
         mutex_init(&hat->hat_mutex, NULL, MUTEX_DEFAULT, NULL);
         ASSERT(hat->hat_flags == 0);
+        hat->hat_unmaps = 0;
 
 #if defined(__xpv)
         /*
          * No VLP stuff on the hypervisor due to the 64-bit split top level
          * page tables.  On 32-bit it's not needed as the hypervisor takes

@@ -399,11 +401,11 @@
          * If the hat is currently a stealing victim, wait for the stealing
          * to finish.  Once we mark it as HAT_FREEING, htable_steal()
          * won't look at its pagetables anymore.
          */
         mutex_enter(&hat_list_lock);
-        while (hat->hat_flags & HAT_VICTIM)
+        while ((hat->hat_flags & HAT_VICTIM) || (hat->hat_unmaps > 0))
                 cv_wait(&hat_list_cv, &hat_list_lock);
         hat->hat_flags |= HAT_FREEING;
         mutex_exit(&hat_list_lock);
 }
 

@@ -2460,36 +2462,21 @@
                 handle_ranges(hat, cb, r_cnt, r);
         XPV_ALLOW_MIGRATE();
 }
 
 /*
- * Invalidate a virtual address translation on a slave CPU during
- * panic() dumps.
+ * Flush the TLB for the local CPU
+ * Invoked from a slave CPU during panic() dumps.
  */
 void
-hat_flush_range(hat_t *hat, caddr_t va, size_t size)
+hat_flush(void)
 {
-        ssize_t sz;
-        caddr_t endva = va + size;
-
-        while (va < endva) {
-                sz = hat_getpagesize(hat, va);
-                if (sz < 0) {
 #ifdef __xpv
                         xen_flush_tlb();
 #else
                         flush_all_tlb_entries();
 #endif
-                        break;
-                }
-#ifdef __xpv
-                xen_flush_va(va);
-#else
-                mmu_tlbflush_entry(va);
-#endif
-                va += sz;
-        }
 }
 
 /*
  * synchronize mapping with software data structures
  *

@@ -3319,22 +3306,39 @@
 hat_page_getattr(struct page *pp, uint_t flag)
 {
         return (PP_GETRM(pp, flag));
 }
 
-
 /*
  * common code used by hat_pageunload() and hment_steal()
  */
 hment_t *
 hati_page_unmap(page_t *pp, htable_t *ht, uint_t entry)
 {
         x86pte_t old_pte;
         pfn_t pfn = pp->p_pagenum;
         hment_t *hm;
+        hat_t *hat = ht->ht_hat;
 
         /*
+         * There is a race between this function and the freeing of a HAT
+         * whose owning process is exiting; process exit code ignores htable
+         * reference counts.
+         * If the HAT is already freeing (HAT_FREEING) no-op this function.
+         * Otherwise increment hat_unmaps to block the hat from being free'd
+         * until this function completes.
+         */
+        mutex_enter(&hat_list_lock);
+        if (hat->hat_flags & HAT_FREEING) {
+                mutex_exit(&hat_list_lock);
+                x86_hm_exit(pp);
+                return (NULL);
+        }
+        ++(hat->hat_unmaps);
+        mutex_exit(&hat_list_lock);
+
+        /*
          * We need to acquire a hold on the htable in order to
          * do the invalidate. We know the htable must exist, since
          * unmap's don't release the htable until after removing any
          * hment. Having x86_hm_enter() keeps that from proceeding.
          */

@@ -3367,15 +3371,19 @@
          * Remove the mapping list entry for this page.
          */
         hm = hment_remove(pp, ht, entry);
 
         /*
-         * drop the mapping list lock so that we might free the
-         * hment and htable.
+         * drop the mapping list lock so that we might free the hment and htable
          */
         x86_hm_exit(pp);
         htable_release(ht);
+
+        mutex_enter(&hat_list_lock);
+        --(hat->hat_unmaps);
+        cv_broadcast(&hat_list_cv);
+        mutex_exit(&hat_list_lock);
         return (hm);
 }
 
 extern int      vpm_enable;
 /*