View | Details | Raw Unified | Return to bug 242137 | Differences between
and this patch

Collapse All | Expand All

(-)sys/amd64/amd64/pmap.c (-34 / +23 lines)
Lines 5214-5221 Link Here
5214
pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot)
5214
pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot)
5215
{
5215
{
5216
	pd_entry_t newpde, oldpde;
5216
	pd_entry_t newpde, oldpde;
5217
	vm_offset_t eva, va;
5217
	vm_page_t m, mt;
5218
	vm_page_t m;
5219
	boolean_t anychanged;
5218
	boolean_t anychanged;
5220
	pt_entry_t PG_G, PG_M, PG_RW;
5219
	pt_entry_t PG_G, PG_M, PG_RW;
5221
5220
Lines 5229-5243 Link Here
5229
	anychanged = FALSE;
5228
	anychanged = FALSE;
5230
retry:
5229
retry:
5231
	oldpde = newpde = *pde;
5230
	oldpde = newpde = *pde;
5232
	if ((oldpde & (PG_MANAGED | PG_M | PG_RW)) ==
5231
	if ((prot & VM_PROT_WRITE) == 0) {
5233
	    (PG_MANAGED | PG_M | PG_RW)) {
5232
		if ((oldpde & (PG_MANAGED | PG_M | PG_RW)) ==
5234
		eva = sva + NBPDR;
5233
		    (PG_MANAGED | PG_M | PG_RW)) {
5235
		for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME);
5234
			m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME);
5236
		    va < eva; va += PAGE_SIZE, m++)
5235
			for (mt = m; mt < &m[NBPDR / PAGE_SIZE]; mt++)
5237
			vm_page_dirty(m);
5236
				vm_page_dirty(mt);
5237
		}
5238
		newpde &= ~(PG_RW | PG_M);
5238
	}
5239
	}
5239
	if ((prot & VM_PROT_WRITE) == 0)
5240
		newpde &= ~(PG_RW | PG_M);
5241
	if ((prot & VM_PROT_EXECUTE) == 0)
5240
	if ((prot & VM_PROT_EXECUTE) == 0)
5242
		newpde |= pg_nx;
5241
		newpde |= pg_nx;
5243
	if (newpde != oldpde) {
5242
	if (newpde != oldpde) {
Lines 7600-7606 Link Here
7600
	pmap_t pmap;
7599
	pmap_t pmap;
7601
	pv_entry_t next_pv, pv;
7600
	pv_entry_t next_pv, pv;
7602
	pd_entry_t oldpde, *pde;
7601
	pd_entry_t oldpde, *pde;
7603
	pt_entry_t oldpte, *pte, PG_M, PG_RW, PG_V;
7602
	pt_entry_t *pte, PG_M, PG_RW;
7604
	struct rwlock *lock;
7603
	struct rwlock *lock;
7605
	vm_offset_t va;
7604
	vm_offset_t va;
7606
	int md_gen, pvh_gen;
7605
	int md_gen, pvh_gen;
Lines 7636-7668 Link Here
7636
			}
7635
			}
7637
		}
7636
		}
7638
		PG_M = pmap_modified_bit(pmap);
7637
		PG_M = pmap_modified_bit(pmap);
7639
		PG_V = pmap_valid_bit(pmap);
7640
		PG_RW = pmap_rw_bit(pmap);
7638
		PG_RW = pmap_rw_bit(pmap);
7641
		va = pv->pv_va;
7639
		va = pv->pv_va;
7642
		pde = pmap_pde(pmap, va);
7640
		pde = pmap_pde(pmap, va);
7643
		oldpde = *pde;
7641
		oldpde = *pde;
7644
		if ((oldpde & PG_RW) != 0) {
7642
		/* If oldpde has PG_RW set, then it also has PG_M set. */
7645
			if (pmap_demote_pde_locked(pmap, pde, va, &lock)) {
7643
		if ((oldpde & PG_RW) != 0 &&
7646
				if ((oldpde & PG_W) == 0) {
7644
		    pmap_demote_pde_locked(pmap, pde, va, &lock) &&
7647
					/*
7645
		    (oldpde & PG_W) == 0) {
7648
					 * Write protect the mapping to a
7646
			/*
7649
					 * single page so that a subsequent
7647
			 * Write protect the mapping to a single page so that
7650
					 * write access may repromote.
7648
			 * a subsequent write access may repromote.
7651
					 */
7649
			 */
7652
					va += VM_PAGE_TO_PHYS(m) - (oldpde &
7650
			va += VM_PAGE_TO_PHYS(m) - (oldpde & PG_PS_FRAME);
7653
					    PG_PS_FRAME);
7651
			pte = pmap_pde_to_pte(pde, va);
7654
					pte = pmap_pde_to_pte(pde, va);
7652
			atomic_clear_long(pte, PG_M | PG_RW);
7655
					oldpte = *pte;
7653
			vm_page_dirty(m);
7656
					if ((oldpte & PG_V) != 0) {
7654
			pmap_invalidate_page(pmap, va);
7657
						while (!atomic_cmpset_long(pte,
7658
						    oldpte,
7659
						    oldpte & ~(PG_M | PG_RW)))
7660
							oldpte = *pte;
7661
						vm_page_dirty(m);
7662
						pmap_invalidate_page(pmap, va);
7663
					}
7664
				}
7665
			}
7666
		}
7655
		}
7667
		PMAP_UNLOCK(pmap);
7656
		PMAP_UNLOCK(pmap);
7668
	}
7657
	}
(-)sys/arm64/arm64/pmap.c (-22 / +16 lines)
Lines 5008-5035 Link Here
5008
		va = pv->pv_va;
5008
		va = pv->pv_va;
5009
		l2 = pmap_l2(pmap, va);
5009
		l2 = pmap_l2(pmap, va);
5010
		oldl2 = pmap_load(l2);
5010
		oldl2 = pmap_load(l2);
5011
		if ((oldl2 & ATTR_SW_DBM) != 0) {
5011
		/* If oldl2 has ATTR_SW_DBM set, then it is also dirty. */
5012
			if (pmap_demote_l2_locked(pmap, l2, va, &lock)) {
5012
		if ((oldl2 & ATTR_SW_DBM) != 0 &&
5013
				if ((oldl2 & ATTR_SW_WIRED) == 0) {
5013
		    pmap_demote_l2_locked(pmap, l2, va, &lock) &&
5014
					/*
5014
		    (oldl2 & ATTR_SW_WIRED) == 0) {
5015
					 * Write protect the mapping to a
5015
			/*
5016
					 * single page so that a subsequent
5016
			 * Write protect the mapping to a single page so that
5017
					 * write access may repromote.
5017
			 * a subsequent write access may repromote.
5018
					 */
5018
			 */
5019
					va += VM_PAGE_TO_PHYS(m) -
5019
			va += VM_PAGE_TO_PHYS(m) - (oldl2 & ~ATTR_MASK);
5020
					    (oldl2 & ~ATTR_MASK);
5020
			l3 = pmap_l2_to_l3(l2, va);
5021
					l3 = pmap_l2_to_l3(l2, va);
5021
			oldl3 = pmap_load(l3);
5022
					oldl3 = pmap_load(l3);
5022
			while (!atomic_fcmpset_long(l3, &oldl3,
5023
					if (pmap_l3_valid(oldl3)) {
5023
			    (oldl3 & ~ATTR_SW_DBM) | ATTR_AP(ATTR_AP_RO)))
5024
						while (!atomic_fcmpset_long(l3,
5024
				cpu_spinwait();
5025
						    &oldl3, (oldl3 & ~ATTR_SW_DBM) |
5025
			vm_page_dirty(m);
5026
						    ATTR_AP(ATTR_AP_RO)))
5026
			pmap_invalidate_page(pmap, va);
5027
							cpu_spinwait();
5028
						vm_page_dirty(m);
5029
						pmap_invalidate_page(pmap, va);
5030
					}
5031
				}
5032
			}
5033
		}
5027
		}
5034
		PMAP_UNLOCK(pmap);
5028
		PMAP_UNLOCK(pmap);
5035
	}
5029
	}
(-)sys/i386/i386/pmap.c (-38 / +28 lines)
Lines 3332-3339 Link Here
3332
pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot)
3332
pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot)
3333
{
3333
{
3334
	pd_entry_t newpde, oldpde;
3334
	pd_entry_t newpde, oldpde;
3335
	vm_offset_t eva, va;
3335
	vm_page_t m, mt;
3336
	vm_page_t m;
3337
	boolean_t anychanged;
3336
	boolean_t anychanged;
3338
3337
3339
	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
3338
	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
Lines 3342-3356 Link Here
3342
	anychanged = FALSE;
3341
	anychanged = FALSE;
3343
retry:
3342
retry:
3344
	oldpde = newpde = *pde;
3343
	oldpde = newpde = *pde;
3345
	if ((oldpde & (PG_MANAGED | PG_M | PG_RW)) ==
3344
	if ((prot & VM_PROT_WRITE) == 0) {
3346
	    (PG_MANAGED | PG_M | PG_RW)) {
3345
		if ((oldpde & (PG_MANAGED | PG_M | PG_RW)) ==
3347
		eva = sva + NBPDR;
3346
		    (PG_MANAGED | PG_M | PG_RW)) {
3348
		for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME);
3347
			m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME);
3349
		    va < eva; va += PAGE_SIZE, m++)
3348
			for (mt = m; mt < &m[NBPDR / PAGE_SIZE]; mt++)
3350
			vm_page_dirty(m);
3349
				vm_page_dirty(mt);
3350
		}
3351
		newpde &= ~(PG_RW | PG_M);
3351
	}
3352
	}
3352
	if ((prot & VM_PROT_WRITE) == 0)
3353
		newpde &= ~(PG_RW | PG_M);
3354
#if defined(PAE) || defined(PAE_TABLES)
3353
#if defined(PAE) || defined(PAE_TABLES)
3355
	if ((prot & VM_PROT_EXECUTE) == 0)
3354
	if ((prot & VM_PROT_EXECUTE) == 0)
3356
		newpde |= pg_nx;
3355
		newpde |= pg_nx;
Lines 5367-5373 Link Here
5367
	pv_entry_t next_pv, pv;
5366
	pv_entry_t next_pv, pv;
5368
	pmap_t pmap;
5367
	pmap_t pmap;
5369
	pd_entry_t oldpde, *pde;
5368
	pd_entry_t oldpde, *pde;
5370
	pt_entry_t oldpte, *pte;
5369
	pt_entry_t *pte;
5371
	vm_offset_t va;
5370
	vm_offset_t va;
5372
5371
5373
	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
5372
	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
Lines 5394-5426 Link Here
5394
		PMAP_LOCK(pmap);
5393
		PMAP_LOCK(pmap);
5395
		pde = pmap_pde(pmap, va);
5394
		pde = pmap_pde(pmap, va);
5396
		oldpde = *pde;
5395
		oldpde = *pde;
5397
		if ((oldpde & PG_RW) != 0) {
5396
		/* If oldpde has PG_RW set, then it also has PG_M set. */
5398
			if (pmap_demote_pde(pmap, pde, va)) {
5397
		if ((oldpde & PG_RW) != 0 &&
5399
				if ((oldpde & PG_W) == 0) {
5398
		    pmap_demote_pde(pmap, pde, va) &&
5400
					/*
5399
		    (oldpde & PG_W) == 0) {
5401
					 * Write protect the mapping to a
5400
			/*
5402
					 * single page so that a subsequent
5401
			 * Write protect the mapping to a single page so that
5403
					 * write access may repromote.
5402
			 * a subsequent write access may repromote.
5404
					 */
5403
			 */
5405
					va += VM_PAGE_TO_PHYS(m) - (oldpde &
5404
			va += VM_PAGE_TO_PHYS(m) - (oldpde & PG_PS_FRAME);
5406
					    PG_PS_FRAME);
5405
			pte = pmap_pte_quick(pmap, va);
5407
					pte = pmap_pte_quick(pmap, va);
5406
			/*
5408
					oldpte = *pte;
5407
			 * Regardless of whether a pte is 32 or 64 bits
5409
					if ((oldpte & PG_V) != 0) {
5408
			 * in size, PG_RW and PG_M are among the least
5410
						/*
5409
			 * significant 32 bits.
5411
						 * Regardless of whether a pte is 32 or 64 bits
5410
			 */
5412
						 * in size, PG_RW and PG_M are among the least
5411
			atomic_clear_int((u_int *)pte, PG_M | PG_RW);
5413
						 * significant 32 bits.
5412
			vm_page_dirty(m);
5414
						 */
5413
			pmap_invalidate_page(pmap, va);
5415
						while (!atomic_cmpset_int((u_int *)pte,
5416
						    oldpte,
5417
						    oldpte & ~(PG_M | PG_RW)))
5418
							oldpte = *pte;
5419
						vm_page_dirty(m);
5420
						pmap_invalidate_page(pmap, va);
5421
					}
5422
				}
5423
			}
5424
		}
5414
		}
5425
		PMAP_UNLOCK(pmap);
5415
		PMAP_UNLOCK(pmap);
5426
	}
5416
	}
(-)sys/riscv/riscv/pmap.c (-23 / +14 lines)
Lines 4104-4110 Link Here
4104
	pmap_t pmap;
4104
	pmap_t pmap;
4105
	pv_entry_t next_pv, pv;
4105
	pv_entry_t next_pv, pv;
4106
	pd_entry_t *l2, oldl2;
4106
	pd_entry_t *l2, oldl2;
4107
	pt_entry_t *l3, oldl3;
4107
	pt_entry_t *l3;
4108
	vm_offset_t va;
4108
	vm_offset_t va;
4109
	int md_gen, pvh_gen;
4109
	int md_gen, pvh_gen;
4110
4110
Lines 4142-4169 Link Here
4142
		va = pv->pv_va;
4142
		va = pv->pv_va;
4143
		l2 = pmap_l2(pmap, va);
4143
		l2 = pmap_l2(pmap, va);
4144
		oldl2 = pmap_load(l2);
4144
		oldl2 = pmap_load(l2);
4145
		if ((oldl2 & PTE_W) != 0) {
4145
		/* If oldl2 has PTE_W set, then it also has PTE_D set. */
4146
			if (pmap_demote_l2_locked(pmap, l2, va, &lock)) {
4146
		if ((oldl2 & PTE_W) != 0 &&
4147
				if ((oldl2 & PTE_SW_WIRED) == 0) {
4147
		    pmap_demote_l2_locked(pmap, l2, va, &lock) &&
4148
					/*
4148
		    (oldl2 & PTE_SW_WIRED) == 0) {
4149
					 * Write protect the mapping to a
4149
			/*
4150
					 * single page so that a subsequent
4150
			 * Write protect the mapping to a single page so that
4151
					 * write access may repromote.
4151
			 * a subsequent write access may repromote.
4152
					 */
4152
			 */
4153
					va += VM_PAGE_TO_PHYS(m) -
4153
			va += VM_PAGE_TO_PHYS(m) - PTE_TO_PHYS(oldl2);
4154
					    PTE_TO_PHYS(oldl2);
4154
			l3 = pmap_l2_to_l3(l2, va);
4155
					l3 = pmap_l2_to_l3(l2, va);
4155
			pmap_clear_bits(l3, PTE_D | PTE_W);
4156
					oldl3 = pmap_load(l3);
4156
			vm_page_dirty(m);
4157
					if ((oldl3 & PTE_V) != 0) {
4157
			pmap_invalidate_page(pmap, va);
4158
						while (!atomic_fcmpset_long(l3,
4159
						    &oldl3, oldl3 & ~(PTE_D |
4160
						    PTE_W)))
4161
							cpu_spinwait();
4162
						vm_page_dirty(m);
4163
						pmap_invalidate_page(pmap, va);
4164
					}
4165
				}
4166
			}
4167
		}
4158
		}
4168
		PMAP_UNLOCK(pmap);
4159
		PMAP_UNLOCK(pmap);
4169
	}
4160
	}

Return to bug 242137