powerpc: introduce pte_set_hidx() helper
[linux-2.6-block.git] / arch / powerpc / include / asm / book3s / 64 / hash-64k.h
index 8d40cf03cb67d10a691bc2d0b92071dbccc0c8e8..c1bd258b7303f6591c2bab3a256a1e0c35537b56 100644 (file)
@@ -68,6 +68,8 @@ static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep)
        return rpte;
 }
 
+#define HIDX_BITS(x, index)  (x << (index << 2))
+
 static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
 {
        if ((pte_val(rpte.pte) & H_PAGE_COMBO))
@@ -75,6 +77,29 @@ static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
        return (pte_val(rpte.pte) >> H_PAGE_F_GIX_SHIFT) & 0xf;
 }
 
+/*
+ * Commit the hidx and return PTE bits that needs to be modified. The caller is
+ * expected to modify the PTE bits accordingly and commit the PTE to memory.
+ */
+static inline unsigned long pte_set_hidx(pte_t *ptep, real_pte_t rpte,
+               unsigned int subpg_index, unsigned long hidx)
+{
+       unsigned long *hidxp = (unsigned long *)(ptep + PTRS_PER_PTE);
+
+       rpte.hidx &= ~HIDX_BITS(0xfUL, subpg_index);
+       *hidxp = rpte.hidx  | HIDX_BITS(hidx, subpg_index);
+
+       /*
+        * Anyone reading PTE must ensure hidx bits are read after reading the
+        * PTE by using the read-side barrier smp_rmb(). __real_pte() can be
+        * used for that.
+        */
+       smp_wmb();
+
+       /* No PTE bits to be modified, return 0x0UL */
+       return 0x0UL;
+}
+
 #define __rpte_to_pte(r)       ((r).pte)
 extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
 /*