[Crash-utility] [PATCH] PPC64: Support virtual to physical address translation (VTOP) for huge pages.

Dave Anderson anderson at redhat.com
Wed Aug 21 15:33:57 UTC 2013



----- 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 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
> 




More information about the Crash-utility mailing list