|
@@ -174,10 +174,25 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
|
|
return;
|
|
return;
|
|
|
|
|
|
if ((pmd_val(pmd) ^ pmd_val(orig)) & _PAGE_PMD_HUGE) {
|
|
if ((pmd_val(pmd) ^ pmd_val(orig)) & _PAGE_PMD_HUGE) {
|
|
- if (pmd_val(pmd) & _PAGE_PMD_HUGE)
|
|
|
|
- mm->context.thp_pte_count++;
|
|
|
|
- else
|
|
|
|
- mm->context.thp_pte_count--;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Note that this routine only sets pmds for THP pages.
|
|
|
|
+ * Hugetlb pages are handled elsewhere. We need to check
|
|
|
|
+ * for huge zero page. Huge zero pages are like hugetlb
|
|
|
|
+ * pages in that there is no RSS, but there is the need
|
|
|
|
+ * for TSB entries. So, huge zero page counts go into
|
|
|
|
+ * hugetlb_pte_count.
|
|
|
|
+ */
|
|
|
|
+ if (pmd_val(pmd) & _PAGE_PMD_HUGE) {
|
|
|
|
+ if (is_huge_zero_page(pmd_page(pmd)))
|
|
|
|
+ mm->context.hugetlb_pte_count++;
|
|
|
|
+ else
|
|
|
|
+ mm->context.thp_pte_count++;
|
|
|
|
+ } else {
|
|
|
|
+ if (is_huge_zero_page(pmd_page(orig)))
|
|
|
|
+ mm->context.hugetlb_pte_count--;
|
|
|
|
+ else
|
|
|
|
+ mm->context.thp_pte_count--;
|
|
|
|
+ }
|
|
|
|
|
|
/* Do not try to allocate the TSB hash table if we
|
|
/* Do not try to allocate the TSB hash table if we
|
|
* don't have one already. We have various locks held
|
|
* don't have one already. We have various locks held
|
|
@@ -204,6 +219,9 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * This routine is only called when splitting a THP
|
|
|
|
+ */
|
|
void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
|
|
void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
|
|
pmd_t *pmdp)
|
|
pmd_t *pmdp)
|
|
{
|
|
{
|
|
@@ -213,6 +231,15 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
|
|
|
|
|
|
set_pmd_at(vma->vm_mm, address, pmdp, entry);
|
|
set_pmd_at(vma->vm_mm, address, pmdp, entry);
|
|
flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
|
|
flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * set_pmd_at() will not be called in a way to decrement
|
|
|
|
+ * thp_pte_count when splitting a THP, so do it now.
|
|
|
|
+ * Sanity check pmd before doing the actual decrement.
|
|
|
|
+ */
|
|
|
|
+ if ((pmd_val(entry) & _PAGE_PMD_HUGE) &&
|
|
|
|
+ !is_huge_zero_page(pmd_page(entry)))
|
|
|
|
+ (vma->vm_mm)->context.thp_pte_count--;
|
|
}
|
|
}
|
|
|
|
|
|
void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
|
|
void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
|