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.
|
||||
|
@ -154,7 +154,7 @@
|
|||
*/
|
||||
|
||||
#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_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)];
|
||||
|
||||
#ifdef XEN
|
||||
if (domid != DOMID_SELF) {
|
||||
int s = splvm();
|
||||
do {
|
||||
opte = *ptep;
|
||||
error = xpq_update_foreign((pt_entry_t *)vtomach((vaddr_t)ptep),
|
||||
npte, domid);
|
||||
splx(s);
|
||||
if (error) {
|
||||
pmap_unmap_ptes(pmap, pmap2);
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* if the same page, inherit PG_U and PG_M.
|
||||
*/
|
||||
if (((opte ^ npte) & (PG_FRAME | PG_V)) == 0) {
|
||||
npte |= opte & (PG_U | PG_M);
|
||||
}
|
||||
} else
|
||||
#endif /* XEN */
|
||||
opte = pmap_pte_testset(ptep, npte); /* zap! */
|
||||
#if defined(XEN)
|
||||
if (domid != DOMID_SELF) {
|
||||
/* 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.
|
||||
|
|
Loading…
Reference in New Issue