[Crash-utility] [PATCH] PPC64: Support virtual to physical address translation (VTOP) for huge pages. (Hari Bathini)
Dave Anderson
anderson at prospeed.net
Wed Aug 14 11:45:37 UTC 2013
Hari,
Thanks for looking into this. I'm currently on vacation and
and so I'll check out this patch next week.
Thanks,
Dave Anderson
>
> 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)
>
> #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 at linux.vnet.ibm.com>
> ---
> 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 at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
>
> End of Crash-utility Digest, Vol 95, Issue 3
> ********************************************
>
>
More information about the Crash-utility
mailing list