----- 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 <[email protected]>
> ---
>  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
> [email protected]
> https://www.redhat.com/mailman/listinfo/crash-utility
> 

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to