pmap_enter:
- when overwriting an existing mapping for the same page, inherit R/M bits so that they won't be lost. - xen: don't leave ptp on error.
This commit is contained in:
parent
f093a1dc3b
commit
569f933f28
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: pmap.c,v 1.40 2008/01/20 21:56:11 yamt Exp $ */
|
/* $NetBSD: pmap.c,v 1.41 2008/01/20 22:41:55 yamt Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Manuel Bouyer.
|
* Copyright (c) 2007 Manuel Bouyer.
|
||||||
|
@ -154,7 +154,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.40 2008/01/20 21:56:11 yamt Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.41 2008/01/20 22:41:55 yamt Exp $");
|
||||||
|
|
||||||
#include "opt_user_ldt.h"
|
#include "opt_user_ldt.h"
|
||||||
#include "opt_lockdebug.h"
|
#include "opt_lockdebug.h"
|
||||||
|
@ -3842,21 +3842,41 @@ pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ptep = &ptes[pl1_i(va)];
|
ptep = &ptes[pl1_i(va)];
|
||||||
|
do {
|
||||||
#ifdef XEN
|
|
||||||
if (domid != DOMID_SELF) {
|
|
||||||
int s = splvm();
|
|
||||||
opte = *ptep;
|
opte = *ptep;
|
||||||
error = xpq_update_foreign((pt_entry_t *)vtomach((vaddr_t)ptep),
|
|
||||||
npte, domid);
|
/*
|
||||||
splx(s);
|
* if the same page, inherit PG_U and PG_M.
|
||||||
if (error) {
|
*/
|
||||||
pmap_unmap_ptes(pmap, pmap2);
|
if (((opte ^ npte) & (PG_FRAME | PG_V)) == 0) {
|
||||||
goto out;
|
npte |= opte & (PG_U | PG_M);
|
||||||
}
|
}
|
||||||
} else
|
#if defined(XEN)
|
||||||
#endif /* XEN */
|
if (domid != DOMID_SELF) {
|
||||||
opte = pmap_pte_testset(ptep, npte); /* zap! */
|
/* pmap_pte_cas with error handling */
|
||||||
|
int s = splvm();
|
||||||
|
if (opte != *ptep) {
|
||||||
|
splx(s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
error = xpq_update_foreign(
|
||||||
|
(pt_entry_t *)vtomach((vaddr_t)ptep), npte, domid);
|
||||||
|
splx(s);
|
||||||
|
if (error) {
|
||||||
|
struct vm_page *empty_ptps = NULL;
|
||||||
|
|
||||||
|
if (ptp != NULL && ptp->wire_count <= 1) {
|
||||||
|
pmap_free_ptp(pmap, ptp, va, ptes, pdes,
|
||||||
|
&empty_ptps);
|
||||||
|
}
|
||||||
|
pmap_unmap_ptes(pmap, pmap2);
|
||||||
|
pmap_free_empty_ptps(empty_ptps);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* defined(XEN) */
|
||||||
|
} while (pmap_pte_cas(ptep, opte, npte) != opte);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* update statistics and PTP's reference count.
|
* update statistics and PTP's reference count.
|
||||||
|
|
Loading…
Reference in New Issue