Hi Dave & Haren, Here are the changes I made to "crash" to function with PPC64 64k pagesize. Instead of adding whole set of indexs, shifts, masks, macros and new vtop() routines - I generalized 4-level pagetable support and set & compute indexes, shift and masks correctly for 4K and 64K. Tested with 4K pagesize and 64K pagesize kernels on PPC64. Please review. Thanks, Badari
--- crash/defs.h 2005-11-17 10:45:13.000000000 -0800 +++ new/defs.h 2005-11-17 11:23:18.000000000 -0800 @@ -2101,23 +2101,14 @@ struct efi_memory_desc_t { #define PGD_OFFSET(vaddr) ((vaddr >> PGDIR_SHIFT) & 0x7ff) #define PMD_OFFSET(vaddr) ((vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) -/* 4-level page table changes */ -#define PGDIR_SHIFT_L4 (PMD_SHIFT + (machdep->pageshift - 5)) -#define L4_SHIFT (PGDIR_SHIFT_L4 + (machdep->pageshift - 5)) - -#define PTE_SHIFT_L4 17 - -#define PTE_INDEX_SIZE_L4 9 -#define PMD_INDEX_SIZE_L4 7 -#define PGD_INDEX_SIZE_L4 7 - -#define PTRS_PER_PTE_L4 (1 << PTE_INDEX_SIZE_L4) -#define PTRS_PER_PMD_L4 (1 << PMD_INDEX_SIZE_L4) -#define PTRS_PER_PGD_L4 (1 << PGD_INDEX_SIZE_L4) - -#define L4_OFFSET(vaddr) ((vaddr >> L4_SHIFT) & 0x1ff) -#define PGD_OFFSET_L4(vaddr) ((vaddr >> PGDIR_SHIFT_L4) & (PTRS_PER_PGD_L4 - 1)) -#define PMD_OFFSET_L4(vaddr) ((vaddr >> PMD_SHIFT) & (PTRS_PER_PMD_L4 - 1)) +/* 4-level page table support */ +#define L4_OFFSET(vaddr) ((vaddr >> (machdep->machspec->l4_shift)) & 0x1ff) + +#define PGD_OFFSET_L4(vaddr) \ + ((vaddr >> (machdep->machspec->l3_shift)) & (machdep->machspec->ptrs_per_l3 - 1)) + +#define PMD_OFFSET_L4(vaddr) \ + ((vaddr >> (machdep->machspec->l2_shift)) & (machdep->machspec->ptrs_per_l2 - 1)) #define _PAGE_PRESENT 0x001UL /* software: pte contains a translation */ #define _PAGE_USER 0x002UL /* matches one of the PP bits */ @@ -3308,6 +3299,23 @@ struct machine_specific { uint hwstacksize; char *level4; ulong last_level4_read; + + uint l4_index_size; + 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; }; #define IS_LAST_L4_READ(l4) ((ulong)(l4) == machdep->machspec->last_level4_read) --- crash/ppc64.c 2005-11-17 10:45:16.000000000 -0800 +++ new/ppc64.c 2005-11-17 11:21:54.000000000 -0800 @@ -122,18 +122,45 @@ ppc64_init(int when) machdep->flags |= VM_ORIG; } } - switch (machdep->flags & (VM_ORIG|VM_4_LEVEL)) - { - case VM_ORIG: - /* pre-2.6.14 layout */ - free(machdep->machspec->level4); - machdep->machspec->level4 = NULL; - machdep->ptrs_per_pgd = PTRS_PER_PGD; - break; - case VM_4_LEVEL: - /* 2.6.14 layout */ - machdep->ptrs_per_pgd = PTRS_PER_PGD_L4; - break; + if (machdep->flags & VM_ORIG) { + /* pre-2.6.14 layout */ + free(machdep->machspec->level4); + machdep->machspec->level4 = NULL; + machdep->ptrs_per_pgd = PTRS_PER_PGD; + } else { + /* 2.6.14 layout */ + struct machine_specific *m = machdep->machspec; + if (machdep->pagesize == 65536) { + /* 64K pagesize */ + m->l1_index_size = 12; + m->l2_index_size = 12; + m->l3_index_size = 0; + m->l4_index_size = 4; + m->l1_shift = 16; + m->pte_shift = 32; + m->l2_masked_bits = 0x1ff; + } else { + /* 4K pagesize */ + m->l1_index_size = 9; + m->l2_index_size = 7; + m->l3_index_size = 7; + m->l4_index_size = 9; + m->l1_shift = 12; + m->pte_shift = 17; + m->l2_masked_bits = 0; + } + + /* Compute ptrs per each level */ + m->ptrs_per_l1 = (1 << m->l1_index_size); + m->ptrs_per_l2 = (1 << m->l2_index_size); + m->ptrs_per_l3 = (1 << m->l3_index_size); + + machdep->ptrs_per_pgd = m->ptrs_per_l3; + + /* Compute shifts */ + m->l2_shift = m->l1_shift + m->l1_index_size; + m->l3_shift = m->l2_shift + m->l2_index_size; + m->l4_shift = m->l3_shift + m->l3_index_size; } machdep->vmalloc_start = ppc64_vmalloc_start; MEMBER_OFFSET_INIT(thread_struct_pg_tables, @@ -413,15 +440,19 @@ ppc64_vtop_level4(ulong vaddr, ulong *le if (!level4_pte) return FALSE; - page_dir = (ulong *)((ulong *)level4_pte + PGD_OFFSET_L4(vaddr)); - FILL_PGD(PAGEBASE(level4_pte), KVADDR, PAGESIZE()); - pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir)); - - if (verbose) - fprintf(fp, " PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte); - - if (!pgd_pte) - return FALSE; + /* 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)); + FILL_PGD(PAGEBASE(level4_pte), KVADDR, PAGESIZE()); + pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir)); + + if (verbose) + fprintf(fp, " PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte); + if (!pgd_pte) + return FALSE; + } else { + pgd_pte = level4_pte; + } page_middle = (ulong *)((ulong *)pgd_pte + PMD_OFFSET_L4(vaddr)); FILL_PMD(PAGEBASE(pgd_pte), KVADDR, PAGESIZE()); @@ -433,7 +464,8 @@ ppc64_vtop_level4(ulong vaddr, ulong *le if (!(pmd_pte)) return FALSE; - page_table = (ulong *)pmd_pte + (BTOP(vaddr) & (PTRS_PER_PTE_L4 - 1)); + page_table = (ulong *)(pmd_pte & ~(machdep->machspec->l2_masked_bits)) + + (BTOP(vaddr) & (machdep->machspec->ptrs_per_l1 - 1)); if (verbose) fprintf(fp, " PMD: %lx => %lx\n",(ulong)page_middle, (ulong)page_table); @@ -447,7 +479,7 @@ ppc64_vtop_level4(ulong vaddr, ulong *le if (!(pte & _PAGE_PRESENT)) { if (pte && verbose) { fprintf(fp, "\n"); - ppc64_translate_pte(pte, 0, PTE_SHIFT_L4); + ppc64_translate_pte(pte, 0, machdep->machspec->pte_shift); } return FALSE; } @@ -455,11 +487,12 @@ ppc64_vtop_level4(ulong vaddr, ulong *le if (!pte) return FALSE; - *paddr = PAGEBASE(PTOB(pte >> PTE_SHIFT_L4)) + PAGEOFFSET(vaddr); + *paddr = PAGEBASE(PTOB(pte >> machdep->machspec->pte_shift)) + + PAGEOFFSET(vaddr); if (verbose) { fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); - ppc64_translate_pte(pte, 0, PTE_SHIFT_L4); + ppc64_translate_pte(pte, 0, machdep->machspec->pte_shift); } return TRUE;