Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/aarch64 fix instability behavior of bu...



details:   https://anonhg.NetBSD.org/src/rev/0e42c8e5d420
branches:  trunk
changeset: 318501:0e42c8e5d420
user:      ryo <ryo%NetBSD.org@localhost>
date:      Fri Apr 27 08:07:08 2018 +0000
description:
fix instability behavior of bufcache on aarch64.
* fix to return correct ref/mod when PMAP_WIRED.
* changed to keep wired flags in pte instead of pv_entry, and cleanup.

diffstat:

 sys/arch/aarch64/aarch64/pmap.c |  223 +++++++++++++--------------------------
 sys/arch/aarch64/include/pmap.h |    7 +-
 2 files changed, 76 insertions(+), 154 deletions(-)

diffs (truncated from 488 to 300 lines):

diff -r bcae74846006 -r 0e42c8e5d420 sys/arch/aarch64/aarch64/pmap.c
--- a/sys/arch/aarch64/aarch64/pmap.c   Fri Apr 27 07:53:07 2018 +0000
+++ b/sys/arch/aarch64/aarch64/pmap.c   Fri Apr 27 08:07:08 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.2 2018/04/01 04:35:03 ryo Exp $     */
+/*     $NetBSD: pmap.c,v 1.3 2018/04/27 08:07:08 ryo Exp $     */
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.2 2018/04/01 04:35:03 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.3 2018/04/27 08:07:08 ryo Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_ddb.h"
@@ -129,8 +129,7 @@
 PMAP_COUNTER(pv_entry_cannotalloc, "pv_entry allocation failure");
 
 PMAP_COUNTER(unwire, "pmap_unwire call");
-PMAP_COUNTER(unwire_unmanaged, "pmap_unwire unmanaged pages");
-PMAP_COUNTER(unwire_wired, "pmap_unwire but already unwire");
+PMAP_COUNTER(unwire_failure, "pmap_unwire failure");
 
 #else /* PMAPCOUNTERS */
 #define PMAP_COUNT(name)               __nothing
@@ -139,6 +138,7 @@
 /* saved permission bit for referenced/modified emulation */
 #define LX_BLKPAG_OS_READ      LX_BLKPAG_OS_0
 #define LX_BLKPAG_OS_WRITE     LX_BLKPAG_OS_1
+#define LX_BLKPAG_OS_WIRED     LX_BLKPAG_OS_2
 #define LX_BLKPAG_OS_RWMASK    (LX_BLKPAG_OS_WRITE|LX_BLKPAG_OS_READ)
 
 /* memory attributes are configured MAIR_EL1 in locore */
@@ -154,7 +154,6 @@
        vaddr_t pv_va;
        paddr_t pv_pa;          /* debug */
        pt_entry_t *pv_ptep;    /* for fast pte lookup */
-       u_int pv_flags;
 };
 
 static pt_entry_t *_pmap_pte_lookup(struct pmap *, vaddr_t);
@@ -876,14 +875,6 @@
        }
        KASSERT(pv != NULL);
 
-       if (pv->pv_flags & PMAP_WIRED) {
-               pm->pm_stats.wired_count--;
-               KDASSERT(md->mdpg_wiredcount > 0);
-               if (--md->mdpg_wiredcount == 0) {
-                       md->mdpg_flags &= ~PMAP_WIRED;
-               }
-       }
-
        TAILQ_REMOVE(&md->mdpg_pvhead, pv, pv_link);
        PMAP_COUNT(pv_remove);
 
@@ -947,8 +938,6 @@
        pr("md=%p\n", md);
        pr(" md->mdpg_flags=%08x %s\n", md->mdpg_flags,
            str_vmflags(md->mdpg_flags));
-       pr(" md->mdpg_kenter=%d\n", md->mdpg_kenter);
-       pr(" md->mdpg_wiredcount=%d\n", md->mdpg_wiredcount);
 
        TAILQ_FOREACH(pv, &md->mdpg_pvhead, pv_link) {
                pr("  pv[%d] pv=%p\n",
@@ -959,7 +948,6 @@
                    i, pv->pv_va, _pmap_color(pv->pv_va));
                pr("    pv[%d].pv_pa   =%016lx (color=%d)\n",
                    i, pv->pv_pa, _pmap_color(pv->pv_pa));
-               pr("    pv[%d].pv_flags=%016lx\n", i, pv->pv_flags);
                i++;
        }
 }
@@ -989,24 +977,7 @@
                }
        }
 
-       if (pv != NULL) {
-               /* update wired count, and mdpg_flags */
-               if ((pv->pv_flags & PMAP_WIRED) && !(flags & PMAP_WIRED)) {
-                       /* wire -> unwire */
-                       pm->pm_stats.wired_count--;
-                       KDASSERT(md->mdpg_wiredcount > 0);
-                       if (--md->mdpg_wiredcount == 0) {
-                               md->mdpg_flags &= ~PMAP_WIRED;
-                       }
-               } else if (!(pv->pv_flags & PMAP_WIRED) &&
-                   (flags & PMAP_WIRED)) {
-                       /* unwire -> wire */
-                       pm->pm_stats.wired_count++;
-                       md->mdpg_wiredcount++;
-                       md->mdpg_flags |= flags;
-               }
-               pv->pv_flags = flags;
-       } else {
+       if (pv == NULL) {
                pmap_pv_unlock(md);
 
                /* create and link new pv */
@@ -1018,18 +989,11 @@
                pv->pv_va = va;
                pv->pv_pa = pa;
                pv->pv_ptep = ptep;
-               pv->pv_flags = flags;
 
                pmap_pv_lock(md);
                TAILQ_INSERT_HEAD(&md->mdpg_pvhead, pv, pv_link);
                PMAP_COUNT(pv_enter);
 
-               if (flags & PMAP_WIRED) {
-                       pm->pm_stats.wired_count++;
-                       if (md->mdpg_wiredcount++ == 0) {
-                               md->mdpg_flags |= PMAP_WIRED;
-                       }
-               }
 #ifdef PMAP_PV_DEBUG
                if (!TAILQ_EMPTY(&md->mdpg_pvhead)){
                        printf("pv %p alias added va=%016lx -> pa=%016lx\n",
@@ -1059,6 +1023,7 @@
 {
        struct pmap *kpm = pmap_kernel();
        vaddr_t eva;
+       int s;
 
        UVMHIST_FUNC(__func__);
        UVMHIST_CALLED(pmaphist);
@@ -1073,9 +1038,11 @@
        eva = va + size;
        KDASSERT(VM_MIN_KERNEL_ADDRESS <= va && eva < VM_MAX_KERNEL_ADDRESS);
 
+       s = splvm();
        for (; va < eva; va += PAGE_SIZE) {
                _pmap_remove(kpm, va, true);
        }
+       splx(s);
 }
 
 static void
@@ -1101,9 +1068,9 @@
 
        /* get prot mask from pte */
        pteprot = 0;
-       if (pte & LX_BLKPAG_OS_READ)
+       if (pte & LX_BLKPAG_AF)
                pteprot |= VM_PROT_READ;
-       if (pte & LX_BLKPAG_OS_WRITE)
+       if ((pte & LX_BLKPAG_AP) == LX_BLKPAG_AP_RW)
                pteprot |= VM_PROT_WRITE;
        if ((pte & (LX_BLKPAG_UXN|LX_BLKPAG_PXN)) == 0)
                pteprot |= VM_PROT_EXECUTE;
@@ -1174,6 +1141,7 @@
                pg = PHYS_TO_VM_PAGE(pa);
 
                if (pg != NULL) {
+                       /* get prot mask from referenced/modified */
                        mdattr = VM_PAGE_TO_MD(pg)->mdpg_flags &
                            (VM_PROT_READ | VM_PROT_WRITE);
                        PMAP_COUNT(protect_managed);
@@ -1359,14 +1327,18 @@
        }
 #endif
 
-       pg = PHYS_TO_VM_PAGE(pa);
+       if (kenter)
+               pg = NULL;
+       else
+               pg = PHYS_TO_VM_PAGE(pa);
+
+#ifdef PMAPCOUNTERS
        if (pg == NULL) {
                PMAP_COUNT(unmanaged_mappings);
-               /* XXX */
-               /* panic("%s:%d", __func__, __LINE__); */
        } else {
                PMAP_COUNT(managed_mappings);
        }
+#endif
 
        /*
         * _pmap_enter() may be called recursively. In case of
@@ -1417,8 +1389,6 @@
        idx = l3pte_index(va);
        ptep = &l3[idx];        /* as PTE */
 
-       /* KASSERT(pg != NULL); */
-
        pte = *ptep;
        executable = l3pte_executable(pte);
 
@@ -1445,46 +1415,41 @@
                            va, l3pte_pa(pte), pa, pte);
 
                        opg = PHYS_TO_VM_PAGE(l3pte_pa(pte));
-                       KASSERT(opg != NULL);
+                       if (opg != NULL)
+                               _pmap_remove_pv(opg, pm, va, pte);
+               }
 
-                       if (opg == pg) {
-                               /* XXX */
-                               panic("%s:%d: XXX: not supported yet",
-                                   __func__, __LINE__);
-                       }
-
-                       _pmap_remove_pv(opg, pm, va, pte);
-               }
+               if (pte & LX_BLKPAG_OS_WIRED)
+                       pm->pm_stats.wired_count--;
+               pm->pm_stats.resident_count--;
        }
 
        /*
         * _pmap_enter_pv() may call pmap_kenter() internally.
         * don't allocate pv_entry (don't call _pmap_enter_pv) when kenter mode.
+        * `pg' have got to be NULL if (kenter).
         */
        mdattr = VM_PROT_READ | VM_PROT_WRITE;
-       if (pg) {
-               if (kenter) {
-                       VM_PAGE_TO_MD(pg)->mdpg_kenter++;
-                       VM_PAGE_TO_MD(pg)->mdpg_flags |= (PMAP_WIRED | mdattr);
-                       VM_PAGE_TO_MD(pg)->mdpg_wiredcount++;
+       if (pg != NULL) {
+               error = _pmap_enter_pv(pg, pm, va, ptep, pa, flags);
+               if (error != 0) {
+                       PMAP_COUNT(pv_entry_cannotalloc);
+                       if (flags & PMAP_CANFAIL)
+                               goto done;
+                       panic(
+                           "pmap_enter: failed to allocate pv_entry");
+               }
 
-                       pm->pm_stats.wired_count++;
+               if (flags & PMAP_WIRED) {
+                       /*
+                        * initial value of ref/mod are equal to prot,
+                        * and pte RW are same as prot.
+                        */
+                       VM_PAGE_TO_MD(pg)->mdpg_flags |=
+                           (prot & mdattr);
                } else {
-                       error = _pmap_enter_pv(pg, pm, va, ptep, pa, flags);
-                       if (error != 0) {
-                               PMAP_COUNT(pv_entry_cannotalloc);
-                               if (flags & PMAP_CANFAIL)
-                                       goto done;
-                               panic(
-                                   "pmap_enter: failed to allocate pv_entry");
-                       }
-
-                       if (flags & PMAP_WIRED) {
-                               VM_PAGE_TO_MD(pg)->mdpg_flags |=
-                                   (PMAP_WIRED | mdattr);
-                       } else {
-                               mdattr &= VM_PAGE_TO_MD(pg)->mdpg_flags;
-                       }
+                       /* pte RW will be masked by ref/mod for ref/mod emul */
+                       mdattr &= VM_PAGE_TO_MD(pg)->mdpg_flags;
                }
        }
 
@@ -1501,6 +1466,8 @@
        attr = _pmap_pte_adjust_cacheflags(attr, flags);
        if (VM_MAXUSER_ADDRESS > va)
                attr |= LX_BLKPAG_APUSER;
+       if (flags & PMAP_WIRED)
+               attr |= LX_BLKPAG_OS_WIRED;
 #ifdef MULTIPROCESSOR
        attr |= LX_BLKPAG_SH_IS;
 #endif
@@ -1520,6 +1487,8 @@
                cpu_icache_sync_range(va, PAGE_SIZE);
        }
 
+       if (pte & LX_BLKPAG_OS_WIRED)
+               pm->pm_stats.wired_count++;
        pm->pm_stats.resident_count++;
 
  done:
@@ -1563,33 +1532,25 @@
                        return;
 
                pa = l3pte_pa(pte);
-               pg = PHYS_TO_VM_PAGE(pa);
-               if (pg != NULL) {
-                       if (kremove) {
-                               struct vm_page_md *md = VM_PAGE_TO_MD(pg);
-
-                               KASSERT(md->mdpg_flags & PMAP_WIRED);
-                               KDASSERT(md->mdpg_kenter > 0);
 
-                               md->mdpg_kenter--;
-                               pm->pm_stats.wired_count--;
-                               KDASSERT(md->mdpg_wiredcount > 0);
-                               if (--md->mdpg_wiredcount == 0) {
-                                       md->mdpg_flags &= ~PMAP_WIRED;
-                               }



Home | Main Index | Thread Index | Old Index