|
@@ -315,48 +315,48 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
|
|
|
|
|
|
+static long __pSeries_lpar_hpte_find(unsigned long want_v, unsigned long hpte_group)
|
|
{
|
|
{
|
|
- unsigned long dword0;
|
|
|
|
- unsigned long lpar_rc;
|
|
|
|
- unsigned long dummy_word1;
|
|
|
|
- unsigned long flags;
|
|
|
|
|
|
+ long lpar_rc;
|
|
|
|
+ unsigned long i, j;
|
|
|
|
+ struct {
|
|
|
|
+ unsigned long pteh;
|
|
|
|
+ unsigned long ptel;
|
|
|
|
+ } ptes[4];
|
|
|
|
|
|
- /* Read 1 pte at a time */
|
|
|
|
- /* Do not need RPN to logical page translation */
|
|
|
|
- /* No cross CEC PFT access */
|
|
|
|
- flags = 0;
|
|
|
|
|
|
+ for (i = 0; i < HPTES_PER_GROUP; i += 4, hpte_group += 4) {
|
|
|
|
|
|
- lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
|
|
|
|
|
|
+ lpar_rc = plpar_pte_read_4(0, hpte_group, (void *)ptes);
|
|
|
|
+ if (lpar_rc != H_SUCCESS)
|
|
|
|
+ continue;
|
|
|
|
|
|
- BUG_ON(lpar_rc != H_SUCCESS);
|
|
|
|
|
|
+ for (j = 0; j < 4; j++) {
|
|
|
|
+ if (HPTE_V_COMPARE(ptes[j].pteh, want_v) &&
|
|
|
|
+ (ptes[j].pteh & HPTE_V_VALID))
|
|
|
|
+ return i + j;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- return dword0;
|
|
|
|
|
|
+ return -1;
|
|
}
|
|
}
|
|
|
|
|
|
static long pSeries_lpar_hpte_find(unsigned long vpn, int psize, int ssize)
|
|
static long pSeries_lpar_hpte_find(unsigned long vpn, int psize, int ssize)
|
|
{
|
|
{
|
|
- unsigned long hash;
|
|
|
|
- unsigned long i;
|
|
|
|
long slot;
|
|
long slot;
|
|
- unsigned long want_v, hpte_v;
|
|
|
|
|
|
+ unsigned long hash;
|
|
|
|
+ unsigned long want_v;
|
|
|
|
+ unsigned long hpte_group;
|
|
|
|
|
|
hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
|
|
hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
|
|
want_v = hpte_encode_avpn(vpn, psize, ssize);
|
|
want_v = hpte_encode_avpn(vpn, psize, ssize);
|
|
|
|
|
|
/* Bolted entries are always in the primary group */
|
|
/* Bolted entries are always in the primary group */
|
|
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
|
|
|
|
- for (i = 0; i < HPTES_PER_GROUP; i++) {
|
|
|
|
- hpte_v = pSeries_lpar_hpte_getword0(slot);
|
|
|
|
-
|
|
|
|
- if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID))
|
|
|
|
- /* HPTE matches */
|
|
|
|
- return slot;
|
|
|
|
- ++slot;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return -1;
|
|
|
|
-}
|
|
|
|
|
|
+ hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
|
|
|
|
+ slot = __pSeries_lpar_hpte_find(want_v, hpte_group);
|
|
|
|
+ if (slot < 0)
|
|
|
|
+ return -1;
|
|
|
|
+ return hpte_group + slot;
|
|
|
|
+}
|
|
|
|
|
|
static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
|
|
static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
|
|
unsigned long ea,
|
|
unsigned long ea,
|