----- Original Message ----- > Crash utility currently does not supporting virtual to physical address > translation for huge pages on PPC64. > This patch tries to address this issue by providing address translation > support for huge pages in 'vtop' command on PPC64. > Below are couple of outputs for address translation of huge pages on > crash-7.0.1 (with Dave's patch for vtop issue on >=3.10 kernel) Hari, This looks good -- queued for crash-7.0.2. Thanks, Dave > > #On kernel release 3.6.0-rc1 > > crash> set 8149 > PID: 8149 > COMMAND: "hugepage-mmap" > TASK: c000000079ce49f0 [THREAD_INFO: c00000007795c000] > CPU: 0 > STATE: TASK_INTERRUPTIBLE > crash> vtop 0xefff0000000 > VIRTUAL PHYSICAL > vtop: invalid kernel virtual address: 4000000079060000 type: "page table" > crash> > > > #On kernel release 3.11.0-rc2 > > crash> set 13011 > PID: 13011 > COMMAND: "hugepage-mmap" > TASK: c000000071600000 [THREAD_INFO: c000000078240000] > CPU: 0 > STATE: TASK_INTERRUPTIBLE > crash> vtop 0x1efff0000000 > VIRTUAL PHYSICAL > 1efff0000000 (not mapped) > > PAGE DIRECTORY: c000000002770000 > L4: c000000002770df8 => 0 > > VMA START END FLAGS FILE > c000000024f13af0 1efff0000000 1f0000000000 4400fb > /mnt/huge/hugepagefile > > FILE: /mnt/huge/hugepagefile OFFSET: 0 > > crash> > > In the two cases mentioned above, crash fails to convert huge pages to > corresponding physical addresses. > Below are the outputs with this patch "applied" > > #On kernel release 3.6.0-rc1 > > crash> vtop 0xefff0000000 > VIRTUAL PHYSICAL > efff0000000 37000000 > > PAGE DIRECTORY: c00000007906f800 > L4: c00000007906f870 => c00000007c588000 > PMD: c00000007c58fff8 => 4000000079063798 > HUGE PAGE: 37000000 > > PTE PHYSICAL FLAGS > dc008000393 37000000 (PRESENT|USER|COHERENT|DIRTY|ACCESSED) > > VMA START END FLAGS FILE > c00000007bf3a140 efff0000000 f0000000000 4800fb > /mnt/huge/hugepagefile > > PAGE PHYSICAL MAPPING INDEX CNT FLAGS > c00000007f380000 37000000 c00000007af00e88 0 2 3701000004018 > crash> > > #On kernel release 3.11.0-rc2 > > crash> vtop 0x1efff0000000 > VIRTUAL PHYSICAL > 1efff0000000 45000000 > > PAGE DIRECTORY: c000000002770000 > L4: c000000002773df8 => c00000007ab80000 > PMD: c00000007ab81f80 => 114008000393 > HUGE PAGE: 45000000 > > PTE PHYSICAL FLAGS > 114008000393 45000000 (PRESENT|USER|COHERENT|DIRTY|ACCESSED) > > VMA START END FLAGS FILE > c000000024f13af0 1efff0000000 1f0000000000 4400fb > /mnt/huge/hugepagefile > > PAGE PHYSICAL MAPPING INDEX CNT FLAGS > c00000007f460000 45000000 c000000072ea0c70 0 2 1140400004018 > crash> > > With the patch applied huge pages could be converted to corresponding > physical pages > from huge pte in 3.11 kernel and from huge page directory on 3.6 kernel > respectively. > Though, there are couple of things still to be taken up (see TODOs). > 1) Only base physical address is returned for a huge page as of now. > 2) Appropraite offset in huge page directory to get the actual physical page > for a given huge page. > > Signed-off-by: Hari Bathini <hbathini@xxxxxxxxxxxxxxxxxx> > --- > defs.h | 6 +++- > ppc64.c | 91 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 92 insertions(+), 5 deletions(-) > > diff --git a/defs.h b/defs.h > index 275697b..7196bc9 100755 > --- a/defs.h > +++ b/defs.h > @@ -3494,7 +3494,11 @@ struct efi_memory_desc_t { > #define PTE_SHIFT_L4_BOOK3E_4K 24 > #define PMD_MASKED_BITS_64K 0x1ff > > -#define L4_OFFSET(vaddr) ((vaddr >> (machdep->machspec->l4_shift)) & 0x1ff) > +#define PD_HUGE 0x8000000000000000 > +#define HUGE_PTE_MASK 0x03 > +#define HUGEPD_SHIFT_MASK 0x3f > +#define L4_MASK (THIS_KERNEL_VERSION >= LINUX(3,10,0) ? 0xfff : > 0x1ff) > +#define L4_OFFSET(vaddr) ((vaddr >> (machdep->machspec->l4_shift)) & > L4_MASK) > > #define PGD_OFFSET_L4(vaddr) \ > ((vaddr >> (machdep->machspec->l3_shift)) & (machdep->machspec->ptrs_per_l3 > - 1)) > diff --git a/ppc64.c b/ppc64.c > index 6f4f623..bf7def3 100755 > --- a/ppc64.c > +++ b/ppc64.c > @@ -55,7 +55,51 @@ static int ppc64_get_cpu_map(void); > static void ppc64_clear_machdep_cache(void); > static void ppc64_vmemmap_init(void); > static int ppc64_get_kvaddr_ranges(struct vaddr_range *); > +static uint get_ptetype(ulong pte); > +static int is_hugepage(ulong pte); > +static int is_hugepd(ulong pte); > +static ulong hugepage_dir(ulong pte); > > +static inline uint get_ptetype(ulong pte) > +{ > + uint pte_type = 0; /* 0: regular entry; 1: huge pte; 2: huge pd */ > + > + if (is_hugepage(pte)) > + pte_type = 1; > + else if (is_hugepd(pte)) > + pte_type = 2; > + > + return pte_type; > +} > + > +static int is_hugepage(ulong pte) > +{ > + /* > + * leaf pte for huge page, bottom two bits != 00 > + */ > + return ((pte & HUGE_PTE_MASK) != 0x0); > +} > + > +static inline int is_hugepd(ulong pte) > +{ > + if (THIS_KERNEL_VERSION >= LINUX(3,10,0)) { > + /* > + * hugepd pointer, bottom two bits == 00 and next 4 bits > + * indicate size of table > + */ > + return (((pte & HUGE_PTE_MASK) == 0x0) && > + ((pte & HUGEPD_SHIFT_MASK) != 0)); > + } else > + return ((pte & PD_HUGE) == 0x0); > +} > + > +static inline ulong hugepage_dir(ulong pte) > +{ > + if (THIS_KERNEL_VERSION >= LINUX(3,10,0)) > + return (ulong)(pte & ~HUGEPD_SHIFT_MASK); > + else > + return (ulong)((pte & ~HUGEPD_SHIFT_MASK) | PD_HUGE); > +} > > static int book3e_is_kvaddr(ulong addr) > { > @@ -637,6 +681,7 @@ ppc64_vtop_level4(ulong vaddr, ulong *level4, physaddr_t > *paddr, int verbose) > ulong *page_table; > ulong level4_pte, pgd_pte, pmd_pte; > ulong pte; > + uint hugepage_type = 0; /* 0: regular entry; 1: huge pte; 2: huge pd */ > > if (verbose) > fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)level4); > @@ -649,6 +694,12 @@ ppc64_vtop_level4(ulong vaddr, ulong *level4, physaddr_t > *paddr, int verbose) > if (!level4_pte) > return FALSE; > > + hugepage_type = get_ptetype(level4_pte); > + if (hugepage_type) { > + pte = level4_pte; > + goto out; > + } > + > /* Sometimes we don't have level3 pagetable entries */ > if (machdep->machspec->l3_index_size != 0) { > page_dir = (ulong *)((ulong *)level4_pte + PGD_OFFSET_L4(vaddr)); > @@ -659,6 +710,12 @@ ppc64_vtop_level4(ulong vaddr, ulong *level4, physaddr_t > *paddr, int verbose) > fprintf(fp, " PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte); > if (!pgd_pte) > return FALSE; > + > + hugepage_type = get_ptetype(pgd_pte); > + if (hugepage_type) { > + pte = pgd_pte; > + goto out; > + } > } else { > pgd_pte = level4_pte; > } > @@ -673,6 +730,12 @@ ppc64_vtop_level4(ulong vaddr, ulong *level4, physaddr_t > *paddr, int verbose) > if (!(pmd_pte)) > return FALSE; > > + hugepage_type = get_ptetype(pmd_pte); > + if (hugepage_type) { > + pte = pmd_pte; > + goto out; > + } > + > page_table = (ulong *)(pmd_pte & ~(machdep->machspec->l2_masked_bits)) > + (BTOP(vaddr) & (machdep->machspec->ptrs_per_l1 - 1)); > if (verbose) > @@ -696,17 +759,37 @@ ppc64_vtop_level4(ulong vaddr, ulong *level4, > physaddr_t *paddr, int verbose) > if (!pte) > return FALSE; > > - *paddr = PAGEBASE(PTOB(pte >> machdep->machspec->pte_shift)) > - + PAGEOFFSET(vaddr); > +out: > + if (hugepage_type) { > + if (hugepage_type == 2) { > + /* TODO: Calculate the offset within the huge page > + * directory for this huge page to get corresponding > + * physical address. In the current form, it may > + * return the physical address of the first huge page > + * in this directory for all the huge pages > + * in this huge page directory. > + */ > + readmem(hugepage_dir(pte), KVADDR, &pte, sizeof(pte), > + "hugepd_entry", RETURN_ON_ERROR); > + } > + /* TODO: get page offset for huge pages based on page size */ > + *paddr = PAGEBASE(PTOB(pte >> machdep->machspec->pte_shift)); > + } else { > + *paddr = PAGEBASE(PTOB(pte >> machdep->machspec->pte_shift)) > + + PAGEOFFSET(vaddr); > + } > > if (verbose) { > - fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); > + if (hugepage_type) > + fprintf(fp, " HUGE PAGE: %lx\n\n", PAGEBASE(*paddr)); > + else > + fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); > ppc64_translate_pte(pte, 0, machdep->machspec->pte_shift); > } > > return TRUE; > } > - > + > /* > * Translates a user virtual address to its physical address. cmd_vtop() > * sets the verbose flag so that the pte translation gets displayed; all > > -- > Crash-utility mailing list > Crash-utility@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/crash-utility > -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility