Module Name:    src
Committed By:   maxv
Date:           Sat Jun  1 08:12:26 UTC 2019

Modified Files:
        src/sys/arch/x86/x86: pmap.c

Log Message:
Fix two bugs in pmap_write_protect():

 * The mask should be ~PAGE_MASK, not PTE_FRAME. PTE_FRAME eliminates the
   higher bits, and that's not wanted.
 * The computation of tva is incorrect: if the VA is in kernel space we
   must take the canonical hole into account, and here we were not.

We've had these bugs basically forever. It meant that uvm_km_protect()
would never flush the correct VA, and a stale TLB entry would persist.

Fixes PR/54257. Since I added PCID support we execute invpcid in invlpg(),
and invpcid triggers a #GP if the address is non canonical, contrary to
invlpg. The wrong computation of the VA during a modload happened to hit
the canonical hole.


To generate a diff of this commit:
cvs rdiff -u -r1.333 -r1.334 src/sys/arch/x86/x86/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/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.333 src/sys/arch/x86/x86/pmap.c:1.334
--- src/sys/arch/x86/x86/pmap.c:1.333	Mon May 27 18:36:37 2019
+++ src/sys/arch/x86/x86/pmap.c	Sat Jun  1 08:12:26 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.333 2019/05/27 18:36:37 maxv Exp $	*/
+/*	$NetBSD: pmap.c,v 1.334 2019/06/01 08:12:26 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.333 2019/05/27 18:36:37 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.334 2019/06/01 08:12:26 maxv Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -4017,7 +4017,7 @@ pmap_write_protect(struct pmap *pmap, va
 	pt_entry_t * const *pdes;
 	struct pmap *pmap2;
 	vaddr_t blockend, va;
-	int lvl;
+	int lvl, i;
 
 	KASSERT(curlwp->l_md.md_gc_pmap != pmap);
 
@@ -4034,8 +4034,8 @@ pmap_write_protect(struct pmap *pmap, va
 	if (!(prot & VM_PROT_EXECUTE))
 		bit_put = pmap_pg_nx;
 
-	sva &= PTE_FRAME;
-	eva &= PTE_FRAME;
+	sva &= ~PAGE_MASK;
+	eva &= ~PAGE_MASK;
 
 	/* Acquire pmap. */
 	kpreempt_disable();
@@ -4058,7 +4058,7 @@ pmap_write_protect(struct pmap *pmap, va
 		spte = &ptes[pl1_i(va)];
 		epte = &ptes[pl1_i(blockend)];
 
-		for (/* */; spte < epte; spte++) {
+		for (i = 0; spte < epte; spte++, i++) {
 			pt_entry_t opte, npte;
 
 			do {
@@ -4070,7 +4070,7 @@ pmap_write_protect(struct pmap *pmap, va
 			} while (pmap_pte_cas(spte, opte, npte) != opte);
 
 			if ((opte & PTE_D) != 0) {
-				vaddr_t tva = x86_ptob(spte - ptes);
+				vaddr_t tva = va + x86_ptob(i);
 				pmap_tlb_shootdown(pmap, tva, opte,
 				    TLBSHOOT_WRITE_PROTECT);
 			}

Reply via email to