|
@@ -68,6 +68,8 @@ static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep)
|
|
return rpte;
|
|
return rpte;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#define HIDX_BITS(x, index) (x << (index << 2))
|
|
|
|
+
|
|
static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
|
|
static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
|
|
{
|
|
{
|
|
if ((pte_val(rpte.pte) & H_PAGE_COMBO))
|
|
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;
|
|
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)
|
|
#define __rpte_to_pte(r) ((r).pte)
|
|
extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
|
|
extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
|
|
/*
|
|
/*
|