summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/pseries
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2013-09-27 13:11:20 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2013-09-27 13:11:20 +0000
commit40809f1aaf52ffccc4f55985e5f79ecec25ea4b9 (patch)
treeb60eb5cd73438f5b0be4acb4f439aaed6209c09e /sys/powerpc/pseries
parentf1a7c5fc501f5bfabeb46b4582616e02055a4de5 (diff)
downloadFreeBSD-src-40809f1aaf52ffccc4f55985e5f79ecec25ea4b9.zip
FreeBSD-src-40809f1aaf52ffccc4f55985e5f79ecec25ea4b9.tar.gz
Make sure that ref and changed bits propagate back to the VM layer
whenever pages are unmapped. The old code had several races that could allow these to become stale. Approved by: re (kib)
Diffstat (limited to 'sys/powerpc/pseries')
-rw-r--r--sys/powerpc/pseries/mmu_phyp.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/sys/powerpc/pseries/mmu_phyp.c b/sys/powerpc/pseries/mmu_phyp.c
index 454bb12..84cc3f5 100644
--- a/sys/powerpc/pseries/mmu_phyp.c
+++ b/sys/powerpc/pseries/mmu_phyp.c
@@ -201,6 +201,7 @@ mphyp_pte_synch(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt)
struct lpte pte;
uint64_t junk;
+ __asm __volatile("ptesync");
phyp_pft_hcall(H_READ, 0, slot, 0, 0, &pte.pte_hi, &pte.pte_lo,
&junk);
@@ -221,9 +222,16 @@ mphyp_pte_clear(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn,
static void
mphyp_pte_unset(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn)
{
+ struct lpte pte;
+ uint64_t junk;
+ int err;
+
+ err = phyp_pft_hcall(H_REMOVE, 1UL << 31, slot,
+ pvo_pt->pte_hi & LPTE_AVPN_MASK, 0, &pte.pte_hi, &pte.pte_lo,
+ &junk);
+ KASSERT(err == H_SUCCESS, ("Error removing page: %d", err));
- /* XXX: last argument can check the VPN -- set flag to enable */
- phyp_hcall(H_REMOVE, 0, slot, vpn);
+ pvo_pt->pte_lo |= pte.pte_lo & (LPTE_CHG | LPTE_REF);
}
static void
@@ -242,9 +250,7 @@ mphyp_pte_change(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn)
("Locked pages not supported on PHYP"));
/* XXX: optimization using H_PROTECT for common case? */
- result = phyp_hcall(H_REMOVE, 0, slot, vpn);
- if (result != H_SUCCESS)
- panic("mphyp_pte_change() invalidation failure: %ld\n", result);
+ mphyp_pte_unset(mmu, slot, pvo_pt, vpn);
result = phyp_pft_hcall(H_ENTER, H_EXACT, slot, pvo_pt->pte_hi,
pvo_pt->pte_lo, &index, &evicted.pte_lo, &junk);
if (result != H_SUCCESS)
@@ -360,7 +366,8 @@ mphyp_pte_insert(mmu_t mmu, u_int ptegidx, struct lpte *pvo_pt)
if (pvo->pvo_pte.lpte.pte_hi == evicted.pte_hi) {
KASSERT(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID,
("Invalid PVO for valid PTE!"));
- phyp_hcall(H_REMOVE, 0, index, 0);
+ mphyp_pte_unset(mmu, index, &pvo->pvo_pte.lpte,
+ pvo->pvo_vpn);
PVO_PTEGIDX_CLR(pvo);
moea64_pte_overflow++;
break;
OpenPOWER on IntegriCloud