On 10/9/2020 5:09 AM, Peter Zijlstra wrote:
(we might not need the #ifdef gunk, but I've not yet dug out my cross
  compilers this morning)

---
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7009,6 +7009,7 @@ static u64 perf_virt_to_phys(u64 virt)
   */
  static u64 __perf_get_page_size(struct mm_struct *mm, unsigned long addr)
  {
+       struct page *page;
        pgd_t *pgd;
        p4d_t *p4d;
        pud_t *pud;
@@ -7030,15 +7031,27 @@ static u64 __perf_get_page_size(struct m
        if (!pud_present(*pud))
                return 0;
- if (pud_leaf(*pud))
+       if (pud_leaf(*pud)) {
+#ifdef pud_page
+               page = pud_page(*pud);
+               if (PageHuge(page))
+                       return page_size(compound_head(page));

I think the page_size() returns the Kernel Page Size of a compound page.
What we want is the MMU page size.

If it's for the generic code, I think it should be a problem for X86.

Thanks,
Kan

+#endif
                return 1ULL << PUD_SHIFT;
+       }
pmd = pmd_offset(pud, addr);
        if (!pmd_present(*pmd))
                return 0;
- if (pmd_leaf(*pmd))
+       if (pmd_leaf(*pmd)) {
+#ifdef pmd_page
+               page = pmd_page(*pmd);
+               if (PageHuge(page))
+                       return page_size(compound_head(page));
+#endif
                return 1ULL << PMD_SHIFT;
+       }
pte = pte_offset_map(pmd, addr);
        if (!pte_present(*pte)) {
@@ -7046,6 +7059,10 @@ static u64 __perf_get_page_size(struct m
                return 0;
        }
+ page = pte_page(*pte);
+       if (PageHuge(page))
+               return page_size(compound_head(page));
+
        pte_unmap(pte);
        return PAGE_SIZE;
  }

Reply via email to