In this patch, initializing of page table information that is to be used for virtual to physical address translation of vmalloc region is added to the initialization sequence. Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com> --- arch/ppc64.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ makedumpfile.c | 7 +++++ makedumpfile.h | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 158 insertions(+), 1 deletion(-) diff --git a/arch/ppc64.c b/arch/ppc64.c index 09c0eb3..dabf2e7 100644 --- a/arch/ppc64.c +++ b/arch/ppc64.c @@ -149,6 +149,58 @@ ppc64_vmemmap_init(void) return TRUE; } +static int +ppc64_vmalloc_init(void) +{ + info->page_buf = (char *)calloc(1, PAGESIZE()); + if (info->page_buf == NULL) { + ERRMSG("Can't allocate memory for page tables. %s\n", + strerror(errno)); + return FALSE; + } + + /* 2.6.14 layout */ + if (info->page_size == 65536) { + /* 64K pagesize */ + if (info->kernel_version >= KERNEL_VERSION(3, 10, 0)) { + info->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10; + info->l2_index_size = PMD_INDEX_SIZE_L4_64K_3_10; + info->l3_index_size = PUD_INDEX_SIZE_L4_64K; + } else { + info->l1_index_size = PTE_INDEX_SIZE_L4_64K; + info->l2_index_size = PMD_INDEX_SIZE_L4_64K; + info->l3_index_size = PUD_INDEX_SIZE_L4_64K; + } + + info->pte_shift = SYMBOL(demote_segment_4k) ? + PTE_SHIFT_L4_64K_V2 : PTE_SHIFT_L4_64K_V1; + info->l2_masked_bits = PMD_MASKED_BITS_64K; + } else { + /* 4K pagesize */ + info->l1_index_size = PTE_INDEX_SIZE_L4_4K; + info->l2_index_size = PMD_INDEX_SIZE_L4_4K; + info->l3_index_size = PUD_INDEX_SIZE_L4_4K; + + info->pte_shift = PTE_SHIFT_L4_4K; + info->l2_masked_bits = PMD_MASKED_BITS_4K; + } + + /* Compute ptrs per each level */ + info->l1_shift = info->page_shift; + info->ptrs_per_l1 = (1 << info->l1_index_size); + info->ptrs_per_l2 = (1 << info->l2_index_size); + info->ptrs_per_l3 = (1 << info->l3_index_size); + + info->ptrs_per_pgd = info->ptrs_per_l3; + + /* Compute shifts */ + info->l2_shift = info->l1_shift + info->l1_index_size; + info->l3_shift = info->l2_shift + info->l2_index_size; + info->l4_shift = info->l3_shift + info->l3_index_size; + + return TRUE; +} + /* * If the vmemmap address translation information is stored in the kernel, * make the translation. @@ -251,6 +303,15 @@ get_machdep_info_ppc64(void) info->vmalloc_start = vmalloc_start; DEBUG_MSG("vmalloc_start: %lx\n", vmalloc_start); + if (SYMBOL(swapper_pg_dir) != NOT_FOUND_SYMBOL) { + info->kernel_pgd = SYMBOL(swapper_pg_dir); + } else if (SYMBOL(cpu_pgd) != NOT_FOUND_SYMBOL) { + info->kernel_pgd = SYMBOL(cpu_pgd); + } else { + ERRMSG("No swapper_pg_dir or cpu_pgd symbols exist\n"); + return FALSE; + } + if (SYMBOL(vmemmap_list) != NOT_FOUND_SYMBOL) { info->vmemmap_start = VMEMMAP_REGION_ID << REGION_SHIFT; info->vmemmap_end = info->vmemmap_start; @@ -265,6 +326,17 @@ get_machdep_info_ppc64(void) } int +get_versiondep_info_ppc64() +{ + if (ppc64_vmalloc_init() == FALSE) { + ERRMSG("Can't initialize for vmalloc translation\n"); + return FALSE; + } + + return TRUE; +} + +int is_vmalloc_addr_ppc64(unsigned long vaddr) { return (info->vmalloc_start && vaddr >= info->vmalloc_start); diff --git a/makedumpfile.c b/makedumpfile.c index 3884aa5..f54ff8f 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -1181,6 +1181,9 @@ get_symbol_info(void) SYMBOL_INIT(mmu_psize_defs, "mmu_psize_defs"); SYMBOL_INIT(mmu_vmemmap_psize, "mmu_vmemmap_psize"); + SYMBOL_INIT(cpu_pgd, "cpu_pgd"); + SYMBOL_INIT(demote_segment_4k, "demote_segment_4k"); + return TRUE; } @@ -1694,6 +1697,8 @@ write_vmcoreinfo_data(void) WRITE_SYMBOL("vmemmap_list", vmemmap_list); WRITE_SYMBOL("mmu_psize_defs", mmu_psize_defs); WRITE_SYMBOL("mmu_vmemmap_psize", mmu_vmemmap_psize); + WRITE_SYMBOL("cpu_pgd", cpu_pgd); + WRITE_SYMBOL("demote_segment_4k", demote_segment_4k); /* * write the structure size of 1st kernel @@ -2033,6 +2038,8 @@ read_vmcoreinfo(void) READ_SYMBOL("vmemmap_list", vmemmap_list); READ_SYMBOL("mmu_psize_defs", mmu_psize_defs); READ_SYMBOL("mmu_vmemmap_psize", mmu_vmemmap_psize); + READ_SYMBOL("cpu_pgd", cpu_pgd); + READ_SYMBOL("demote_segment_4k", demote_segment_4k); READ_STRUCTURE_SIZE("page", page); READ_STRUCTURE_SIZE("mem_section", mem_section); diff --git a/makedumpfile.h b/makedumpfile.h index 9402f05..7816241 100644 --- a/makedumpfile.h +++ b/makedumpfile.h @@ -586,6 +586,58 @@ do { \ #define _MAX_PHYSMEM_BITS_3_7 (46) #define REGION_SHIFT (60UL) #define VMEMMAP_REGION_ID (0xfUL) + +#define PGDIR_SHIFT \ + (info->page_shift + (info->page_shift -3) + (info->page_shift - 2)) +#define PMD_SHIFT (info->page_shift + (info->page_shift - 3)) + +/* shift to put page number into pte */ +#define PTE_SHIFT 16 + +#define PTE_INDEX_SIZE 9 +#define PMD_INDEX_SIZE 10 +#define PGD_INDEX_SIZE 10 + +#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) +#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) + +#define PGD_OFFSET(vaddr) ((vaddr >> PGDIR_SHIFT) & 0x7ff) +#define PMD_OFFSET(vaddr) ((vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) + +/* 4-level page table support */ + +/* 4K pagesize */ +#define PTE_INDEX_SIZE_L4_4K 9 +#define PMD_INDEX_SIZE_L4_4K 7 +#define PUD_INDEX_SIZE_L4_4K 7 +#define PGD_INDEX_SIZE_L4_4K 9 +#define PTE_SHIFT_L4_4K 17 +#define PMD_MASKED_BITS_4K 0 + +/* 64K pagesize */ +#define PTE_INDEX_SIZE_L4_64K 12 +#define PMD_INDEX_SIZE_L4_64K 12 +#define PUD_INDEX_SIZE_L4_64K 0 +#define PGD_INDEX_SIZE_L4_64K 4 +#define PTE_INDEX_SIZE_L4_64K_3_10 8 +#define PMD_INDEX_SIZE_L4_64K_3_10 10 +#define PGD_INDEX_SIZE_L4_64K_3_10 12 +#define PTE_SHIFT_L4_64K_V1 32 +#define PTE_SHIFT_L4_64K_V2 30 +#define PMD_MASKED_BITS_64K 0x1ff + +#define L4_MASK \ + (info->kernel_version >= KERNEL_VERSION(3, 10, 0) ? 0xfff : 0x1ff) +#define L4_OFFSET(vaddr) ((vaddr >> (info->l4_shift)) & L4_MASK) + +#define PGD_OFFSET_L4(vaddr) \ + ((vaddr >> (info->l3_shift)) & (info->ptrs_per_l3 - 1)) + +#define PMD_OFFSET_L4(vaddr) \ + ((vaddr >> (info->l2_shift)) & (info->ptrs_per_l2 - 1)) + +#define _PAGE_PRESENT 0x1UL #endif #ifdef __powerpc32__ @@ -731,10 +783,11 @@ unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr); #ifdef __powerpc64__ /* powerpc64 */ int get_machdep_info_ppc64(void); +int get_versiondep_info_ppc64(void); unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr); #define get_phys_base() TRUE #define get_machdep_info() get_machdep_info_ppc64() -#define get_versiondep_info() TRUE +#define get_versiondep_info() get_versiondep_info_ppc64() #define vaddr_to_paddr(X) vaddr_to_paddr_ppc64(X) #endif /* powerpc64 */ @@ -932,6 +985,25 @@ struct DumpInfo { struct ppc64_vmemmap *vmemmap_list; /* + * page table info for ppc64 + */ + int ptrs_per_pgd; + uint l3_index_size; + uint l2_index_size; + uint l1_index_size; + uint ptrs_per_l3; + uint ptrs_per_l2; + uint ptrs_per_l1; + uint l4_shift; + uint l3_shift; + uint l2_shift; + uint l1_shift; + uint pte_shift; + uint l2_masked_bits; + ulong kernel_pgd; + char *page_buf; /* A page buffer to hold page table data */ + + /* * Filter config file containing filter commands to filter out kernel * data from vmcore. */ @@ -1192,6 +1264,12 @@ struct symbol_table { unsigned long long vmemmap_list; unsigned long long mmu_vmemmap_psize; unsigned long long mmu_psize_defs; + + /* + * vm related symbols for ppc64 arch + */ + unsigned long long cpu_pgd; + unsigned long long demote_segment_4k; }; struct size_table {