Module Name:    src
Committed By:   maxv
Date:           Sun Mar 10 16:30:01 UTC 2019

Modified Files:
        src/sys/arch/x86/include: pmap.h
        src/sys/arch/x86/x86: pmap.c
        src/sys/arch/xen/x86: xen_pmap.c

Log Message:
Two changes:

 * Allow large pages to be passed in pmap_pdes_valid, this happens under
   DDB when it reads RIP (.text), called via pmap_extract.

 * Invert a branch in pmap_extract, so that 'l_cpu' is not touched if we're
   dealing with the kernel pmap.

This fixes 'boot -d'.


To generate a diff of this commit:
cvs rdiff -u -r1.99 -r1.100 src/sys/arch/x86/include/pmap.h
cvs rdiff -u -r1.329 -r1.330 src/sys/arch/x86/x86/pmap.c
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/xen/x86/xen_pmap.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/include/pmap.h
diff -u src/sys/arch/x86/include/pmap.h:1.99 src/sys/arch/x86/include/pmap.h:1.100
--- src/sys/arch/x86/include/pmap.h:1.99	Sat Mar  9 08:42:26 2019
+++ src/sys/arch/x86/include/pmap.h	Sun Mar 10 16:30:01 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.99 2019/03/09 08:42:26 maxv Exp $	*/
+/*	$NetBSD: pmap.h,v 1.100 2019/03/10 16:30:01 maxv Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -372,7 +372,8 @@ void		pmap_map_ptes(struct pmap *, struc
 		    pd_entry_t * const **);
 void		pmap_unmap_ptes(struct pmap *, struct pmap *);
 
-int		pmap_pdes_invalid(vaddr_t, pd_entry_t * const *, pd_entry_t *);
+bool		pmap_pdes_valid(vaddr_t, pd_entry_t * const *, pd_entry_t *,
+		    int *lastlvl);
 
 u_int		x86_mmap_flags(paddr_t);
 
@@ -424,12 +425,6 @@ bool	pmap_pageidlezero(paddr_t);
  * inline functions
  */
 
-__inline static bool __unused
-pmap_pdes_valid(vaddr_t va, pd_entry_t * const *pdes, pd_entry_t *lastpde)
-{
-	return pmap_pdes_invalid(va, pdes, lastpde) == 0;
-}
-
 /*
  * pmap_update_pg: flush one page from the TLB (or flush the whole thing
  *	if hardware doesn't support one-page flushing)

Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.329 src/sys/arch/x86/x86/pmap.c:1.330
--- src/sys/arch/x86/x86/pmap.c:1.329	Sat Mar  9 08:42:26 2019
+++ src/sys/arch/x86/x86/pmap.c	Sun Mar 10 16:30:01 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.329 2019/03/09 08:42:26 maxv Exp $	*/
+/*	$NetBSD: pmap.c,v 1.330 2019/03/10 16:30:01 maxv Exp $	*/
 
 /*
  * Copyright (c) 2008, 2010, 2016, 2017 The NetBSD Foundation, Inc.
@@ -130,7 +130,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.329 2019/03/09 08:42:26 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.330 2019/03/10 16:30:01 maxv Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -3031,22 +3031,28 @@ pmap_deactivate(struct lwp *l)
  * some misc. functions
  */
 
-int
-pmap_pdes_invalid(vaddr_t va, pd_entry_t * const *pdes, pd_entry_t *lastpde)
+bool
+pmap_pdes_valid(vaddr_t va, pd_entry_t * const *pdes, pd_entry_t *lastpde,
+    int *lastlvl)
 {
-	int i;
 	unsigned long index;
 	pd_entry_t pde;
+	int i;
 
 	for (i = PTP_LEVELS; i > 1; i--) {
 		index = pl_i(va, i);
 		pde = pdes[i - 2][index];
-		if ((pde & PTE_P) == 0)
-			return i;
+		if ((pde & PTE_P) == 0) {
+			*lastlvl = i;
+			return false;
+		}
+		if (pde & PTE_PS)
+			break;
 	}
 	if (lastpde != NULL)
 		*lastpde = pde;
-	return 0;
+	*lastlvl = i;
+	return true;
 }
 
 /*
@@ -3063,6 +3069,7 @@ pmap_extract(struct pmap *pmap, vaddr_t 
 	paddr_t pa;
 	lwp_t *l;
 	bool hard, rv;
+	int lvl;
 
 	if (__predict_false(pmap->pm_extract != NULL)) {
 		return (*pmap->pm_extract)(pmap, va, pap);
@@ -3083,8 +3090,8 @@ pmap_extract(struct pmap *pmap, vaddr_t 
 
 	kpreempt_disable();
 	ci = l->l_cpu;
-	if (__predict_true(!ci->ci_want_pmapload && ci->ci_pmap == pmap) ||
-	    pmap == pmap_kernel()) {
+	if (pmap == pmap_kernel() ||
+	    __predict_true(!ci->ci_want_pmapload && ci->ci_pmap == pmap)) {
 		/*
 		 * no need to lock, because it's pmap_kernel() or our
 		 * own pmap and is active.  if a user pmap, the caller
@@ -3101,14 +3108,17 @@ pmap_extract(struct pmap *pmap, vaddr_t 
 		hard = true;
 		pmap_map_ptes(pmap, &pmap2, &ptes, &pdes);
 	}
-	if (pmap_pdes_valid(va, pdes, &pde)) {
-		pte = ptes[pl1_i(va)];
-		if (pde & PTE_PS) {
+	if (pmap_pdes_valid(va, pdes, &pde, &lvl)) {
+		if (lvl == 2) {
 			pa = (pde & PTE_LGFRAME) | (va & (NBPD_L2 - 1));
 			rv = true;
-		} else if (__predict_true((pte & PTE_P) != 0)) {
-			pa = pmap_pte2pa(pte) | (va & (NBPD_L1 - 1));
-			rv = true;
+		} else {
+			KASSERT(lvl == 1);
+			pte = ptes[pl1_i(va)];
+			if (__predict_true((pte & PTE_P) != 0)) {
+				pa = pmap_pte2pa(pte) | (va & (NBPD_L1 - 1));
+				rv = true;
+			}
 		}
 	}
 	if (__predict_false(hard)) {
@@ -3531,6 +3541,7 @@ pmap_remove(struct pmap *pmap, vaddr_t s
 	vaddr_t blkendva, va = sva;
 	struct vm_page *ptp;
 	struct pmap *pmap2;
+	int lvl;
 
 	if (__predict_false(pmap->pm_remove != NULL)) {
 		(*pmap->pm_remove)(pmap, sva, eva);
@@ -3545,7 +3556,8 @@ pmap_remove(struct pmap *pmap, vaddr_t s
 	 */
 
 	if (va + PAGE_SIZE == eva) {
-		if (pmap_pdes_valid(va, pdes, &pde)) {
+		if (pmap_pdes_valid(va, pdes, &pde, &lvl)) {
+			KASSERT(lvl == 1);
 
 			/* PA of the PTP */
 			ptppa = pmap_pte2pa(pde);
@@ -3572,19 +3584,17 @@ pmap_remove(struct pmap *pmap, vaddr_t s
 				pmap_free_ptp(pmap, ptp, va, ptes, pdes);
 		}
 	} else for (/* null */ ; va < eva ; va = blkendva) {
-		int lvl;
-
 		/* determine range of block */
 		blkendva = x86_round_pdr(va+1);
 		if (blkendva > eva)
 			blkendva = eva;
 
-		lvl = pmap_pdes_invalid(va, pdes, &pde);
-		if (lvl != 0) {
+		if (!pmap_pdes_valid(va, pdes, &pde, &lvl)) {
 			/* Skip a range corresponding to an invalid pde. */
 			blkendva = (va & ptp_frames[lvl - 1]) + nbpd[lvl - 1];
  			continue;
 		}
+		KASSERT(lvl == 1);
 
 		/* PA of the PTP */
 		ptppa = pmap_pte2pa(pde);
@@ -4003,6 +4013,7 @@ pmap_write_protect(struct pmap *pmap, va
 	pt_entry_t * const *pdes;
 	struct pmap *pmap2;
 	vaddr_t blockend, va;
+	int lvl;
 
 	KASSERT(curlwp->l_md.md_gc_pmap != pmap);
 
@@ -4034,10 +4045,11 @@ pmap_write_protect(struct pmap *pmap, va
 			blockend = eva;
 
 		/* Is it a valid block? */
-		if (!pmap_pdes_valid(va, pdes, NULL)) {
+		if (!pmap_pdes_valid(va, pdes, NULL, &lvl)) {
 			continue;
 		}
 		KASSERT(va < VM_MAXUSER_ADDRESS || va >= VM_MAX_ADDRESS);
+		KASSERT(lvl == 1);
 
 		spte = &ptes[pl1_i(va)];
 		epte = &ptes[pl1_i(blockend)];
@@ -4078,6 +4090,7 @@ pmap_unwire(struct pmap *pmap, vaddr_t v
 	pt_entry_t *ptes, *ptep, opte;
 	pd_entry_t * const *pdes;
 	struct pmap *pmap2;
+	int lvl;
 
 	if (__predict_false(pmap->pm_unwire != NULL)) {
 		(*pmap->pm_unwire)(pmap, va);
@@ -4088,9 +4101,10 @@ pmap_unwire(struct pmap *pmap, vaddr_t v
 	kpreempt_disable();
 	pmap_map_ptes(pmap, &pmap2, &ptes, &pdes);
 
-	if (!pmap_pdes_valid(va, pdes, NULL)) {
+	if (!pmap_pdes_valid(va, pdes, NULL, &lvl)) {
 		panic("%s: invalid PDE va=%#" PRIxVADDR, __func__, va);
 	}
+	KASSERT(lvl == 1);
 
 	ptep = &ptes[pl1_i(va)];
 	opte = *ptep;
@@ -4623,6 +4637,7 @@ pmap_dump(struct pmap *pmap, vaddr_t sva
 	pd_entry_t * const *pdes;
 	struct pmap *pmap2;
 	vaddr_t blkendva;
+	int lvl;
 
 	/*
 	 * if end is out of range truncate.
@@ -4651,8 +4666,9 @@ pmap_dump(struct pmap *pmap, vaddr_t sva
 			blkendva = eva;
 
 		/* valid block? */
-		if (!pmap_pdes_valid(sva, pdes, NULL))
+		if (!pmap_pdes_valid(sva, pdes, NULL, &lvl))
 			continue;
+		KASSERT(lvl == 1);
 
 		pte = &ptes[pl1_i(sva)];
 		for (/* null */; sva < blkendva ; sva += PAGE_SIZE, pte++) {

Index: src/sys/arch/xen/x86/xen_pmap.c
diff -u src/sys/arch/xen/x86/xen_pmap.c:1.30 src/sys/arch/xen/x86/xen_pmap.c:1.31
--- src/sys/arch/xen/x86/xen_pmap.c:1.30	Sat Mar  9 08:42:25 2019
+++ src/sys/arch/xen/x86/xen_pmap.c	Sun Mar 10 16:30:01 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: xen_pmap.c,v 1.30 2019/03/09 08:42:25 maxv Exp $	*/
+/*	$NetBSD: xen_pmap.c,v 1.31 2019/03/10 16:30:01 maxv Exp $	*/
 
 /*
  * Copyright (c) 2007 Manuel Bouyer.
@@ -101,7 +101,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xen_pmap.c,v 1.30 2019/03/09 08:42:25 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_pmap.c,v 1.31 2019/03/10 16:30:01 maxv Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -212,15 +212,17 @@ pmap_extract_ma(struct pmap *pmap, vaddr
 	pd_entry_t pde;
 	pd_entry_t * const *pdes;
 	struct pmap *pmap2;
+	int lvl;
 
 	kpreempt_disable();
 	pmap_map_ptes(pmap, &pmap2, &ptes, &pdes);
-	if (!pmap_pdes_valid(va, pdes, &pde)) {
+	if (!pmap_pdes_valid(va, pdes, &pde, &lvl)) {
 		pmap_unmap_ptes(pmap, pmap2);
 		kpreempt_enable();
 		return false;
 	}
 
+	KASSERT(lvl == 1);
 	pte = ptes[pl1_i(va)];
 	pmap_unmap_ptes(pmap, pmap2);
 	kpreempt_enable();

Reply via email to