Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 May 2011 03:22:41 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r221979 - projects/pseries/powerpc/pseries
Message-ID:  <201105160322.p4G3MfM1064232@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Mon May 16 03:22:41 2011
New Revision: 221979
URL: http://svn.freebsd.org/changeset/base/221979

Log:
  First draft of power hypervisor page replacement algorithm.

Modified:
  projects/pseries/powerpc/pseries/mmu_phyp.c

Modified: projects/pseries/powerpc/pseries/mmu_phyp.c
==============================================================================
--- projects/pseries/powerpc/pseries/mmu_phyp.c	Sun May 15 23:54:45 2011	(r221978)
+++ projects/pseries/powerpc/pseries/mmu_phyp.c	Mon May 16 03:22:41 2011	(r221979)
@@ -218,11 +218,45 @@ mphyp_pte_change(mmu_t mmu, uintptr_t sl
 		panic("mphyp_pte_change() insertion failure: %ld\n", result);
 }
 
+static __inline int
+mphyp_pte_spillable_ident(u_int ptegidx, struct lpte *to_evict)
+{
+	uint64_t slot, junk, k;
+	struct lpte pt;
+	int     i, j;
+
+	/* Start at a random slot */
+	i = mftb() % 8;
+	k = -1;
+	for (j = 0; j < 8; j++) {
+		slot = (ptegidx << 3) + (i + j) % 8;
+		phyp_pft_hcall(H_READ, 0, slot, 0, 0, &pt.pte_hi, &pt.pte_lo,
+		    &junk);
+		
+		if (pt.pte_hi & (LPTE_LOCKED | LPTE_WIRED))
+			continue;
+
+		/* This is a candidate, so remember it */
+		k = slot;
+
+		/* Try to get a page that has not been used lately */
+		if (!(pt.pte_lo & LPTE_REF)) {
+			memcpy(to_evict, &pt, sizeof(struct lpte));
+			return (k);
+		}
+	}
+
+	phyp_pft_hcall(H_READ, 0, slot, 0, 0, &to_evict->pte_hi,
+	    &to_evict->pte_lo, &junk);
+	return (k);
+}
+
 static int
 mphyp_pte_insert(mmu_t mmu, u_int ptegidx, struct lpte *pvo_pt)
 {
 	int64_t result;
 	struct lpte evicted;
+	struct pvo_entry *pvo;
 	uint64_t index, junk;
 	u_int pteg_bktidx;
 
@@ -238,9 +272,12 @@ mphyp_pte_insert(mmu_t mmu, u_int ptegid
 	    pvo_pt->pte_lo, &index, &evicted.pte_lo, &junk);
 	if (result == H_SUCCESS)
 		return (index & 0x07);
+	KASSERT(result == H_PTEG_FULL, ("Page insertion error: %ld "
+	    "(ptegidx: %#x/%#x, PTE %#lx/%#lx", result, ptegidx,
+	    moea64_pteg_count, pvo_pt->pte_hi, pvo_pt->pte_lo));
 
 	/*
-	 * First try primary hash.
+	 * Next try secondary hash.
 	 */
 	pteg_bktidx ^= moea64_pteg_mask;
 	pvo_pt->pte_hi |= LPTE_HID;
@@ -248,8 +285,62 @@ mphyp_pte_insert(mmu_t mmu, u_int ptegid
 	    pvo_pt->pte_hi, pvo_pt->pte_lo, &index, &evicted.pte_lo, &junk);
 	if (result == H_SUCCESS)
 		return (index & 0x07);
+	KASSERT(result == H_PTEG_FULL, ("Secondary page insertion error: %ld",
+	    result));
+
+	/*
+	 * Out of luck. Find a PTE to sacrifice.
+	 */
+	pteg_bktidx = ptegidx;
+	index = mphyp_pte_spillable_ident(pteg_bktidx, &evicted);
+	if (index == -1L) {
+		pteg_bktidx ^= moea64_pteg_mask;
+		index = mphyp_pte_spillable_ident(pteg_bktidx, &evicted);
+	}
+
+	if (index == -1L) {
+		/* No freeable slots in either PTEG? We're hosed. */
+		panic("mphyp_pte_insert: overflow");
+		return (-1);
+	}
+
+	if (pteg_bktidx == ptegidx)
+                pvo_pt->pte_hi &= ~LPTE_HID;
+        else
+                pvo_pt->pte_hi |= LPTE_HID;
+
+	/*
+	 * Synchronize the sacrifice PTE with its PVO, then mark both
+	 * invalid. The PVO will be reused when/if the VM system comes
+	 * here after a fault.
+	 */
+
+	if (evicted.pte_hi & LPTE_HID)
+		pteg_bktidx ^= moea64_pteg_mask; /* PTEs indexed by primary */
+
+	LIST_FOREACH(pvo, &moea64_pvo_table[pteg_bktidx], pvo_olink) {
+		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);
+			PVO_PTEGIDX_CLR(pvo);
+			moea64_pte_overflow++;
+			break;
+		}
+	}
+
+	KASSERT(pvo->pvo_pte.lpte.pte_hi == evicted.pte_hi,
+	   ("Unable to find PVO for spilled PTE"));
+
+	/*
+	 * Set the new PTE.
+	 */
+	result = phyp_pft_hcall(H_ENTER, H_EXACT, index, pvo_pt->pte_hi,
+	    pvo_pt->pte_lo, &index, &evicted.pte_lo, &junk);
+	if (result == H_SUCCESS)
+		return (index & 0x07);
 
-	panic("OVERFLOW (%ld)", result);
+	panic("Page replacement error: %ld", result);
 	return (-1);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105160322.p4G3MfM1064232>