On Thu, 2005-11-17 at 13:18 -0800, Haren Myneni wrote: > > But it's your call... so when you and Haren are happy, just let > > me know. > > Badari, Thanks a lot for doing this. This approach is useful to > support easily even for future changes. One minor comment, instead of > hardcoding in ppc64.c source file for 'm->l1_index_size = 9', can we > define INDEX macros in the header file and use them here. For > example, PTE_INDEX_SIZE_L4. I am thinking we can map/understand easily > to see what is l1 or l2. What do you think? Okay, here is the latest to include what Dave and Haren want. Please review. Thanks, Badari
--- crash/defs.h 2005-11-17 10:45:13.000000000 -0800 +++ new/defs.h 2005-11-17 14:44:14.000000000 -0800 @@ -2101,23 +2101,31 @@ 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 */ + +/* 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_SHIFT_L4_64K 32 +#define PMD_MASKED_BITS_64K 0x1ff + +#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 +3316,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 14:38:33.000000000 -0800 @@ -122,18 +122,44 @@ 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 = PTE_INDEX_SIZE_L4_64K; + m->l2_index_size = PMD_INDEX_SIZE_L4_64K; + m->l3_index_size = PUD_INDEX_SIZE_L4_64K; + m->l4_index_size = PGD_INDEX_SIZE_L4_64K; + m->pte_shift = PTE_SHIFT_L4_64K; + m->l2_masked_bits = PMD_MASKED_BITS_64K; + } else { + /* 4K pagesize */ + m->l1_index_size = PTE_INDEX_SIZE_L4_4K; + m->l2_index_size = PMD_INDEX_SIZE_L4_4K; + m->l3_index_size = PUD_INDEX_SIZE_L4_4K; + m->l4_index_size = PGD_INDEX_SIZE_L4_4K; + m->pte_shift = PTE_SHIFT_L4_4K; + m->l2_masked_bits = PMD_MASKED_BITS_4K; + } + + /* Compute ptrs per each level */ + m->l1_shift = machdep->pageshift; + 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, @@ -306,6 +332,10 @@ ppc64_dump_machdep_table(ulong arg) fprintf(fp, " ptbl: %lx\n", (ulong)machdep->ptbl); fprintf(fp, " ptrs_per_pgd: %d\n", machdep->ptrs_per_pgd); fprintf(fp, " machspec: %lx\n", (ulong)machdep->machspec); + fprintf(fp, " pgd_index_size: %ld\n", machdep->machspec->l4_index_size); + fprintf(fp, " pud_index_size: %ld\n", machdep->machspec->l3_index_size); + fprintf(fp, " pmd_index_size: %ld\n", machdep->machspec->l2_index_size); + fprintf(fp, " pte_index_size: %ld\n", machdep->machspec->l1_index_size); } /* @@ -413,15 +443,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 +467,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 +482,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 +490,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;