This patch update ppc32 vtop. - Translate kvaddr for fsl-booke by using TLBCAM setting - Remove PMD from display because virtual address bit is not assigned - Fixup displayed PHYSICAL values of fsl-booke PTE format - Fixup bug for page flags setup which I made previous patch Updated command images are below. - kvaddr can be translated by using TLBCAM crash> sym powerpc_base_platform c0913024 (S) powerpc_base_platform crash> vtop c0913024 VIRTUAL PHYSICAL c0913024 913024 PAGE DIRECTORY: c08d1000 PGD: c08d2810 => 0 TLBCAM[0]: MAS0 MAS1 MAS2 MAS3 MAS7 10000001 c0000900 c0000004 15 0 VIRTUAL RANGE : c0000000 - cfffffff PHYSICAL RANGE: 0 - fffffff => VIRTUAL PHYSICAL TLBCAM-OFFSET c0913024 913024 9515044 PAGE PHYSICAL MAPPING INDEX CNT FLAGS d0012260 913000 0 0 1 400 Next, - vtop won't display PMD - physical address is not equal to PTE - FLAGS can be handled well crash> vtop -c 4145 10000000 VIRTUAL PHYSICAL 10000000 ef448000 PAGE DIRECTORY: e85c4000 PGD: e85c4200 => e873c000 PTE: e873c000 => ef44824020d PAGE: ef448000 PTE PHYSICAL FLAGS ef44824020d ef448000 (PRESENT|USER|COHERENT|ACCESSED) VMA START END FLAGS FILE ea1d3960 10000000 10af9000 8001875 /tmp/toshi/crash However, ... could not read vtop'd physical address data from /dev/mem now. crash> rd -p ef448000 rd: read error: physical address: ef448000 type: "32-bit PHYSADDR" Although my environment tends to set higher PTE value, PFN is valid physical scope number, my maximum is 4GB. crash> log | grep totalpages On node 0 totalpages: 1048576 crash> eval 1048576 hexadecimal: 100000 (1MB) decimal: 1048576 octal: 4000000 binary: 00000000000100000000000000000000 Is there any constraint in "rd" or is my "/dev/mem" something wrong? Thanks, Toshi Toshikazu Nakayama (5): ppc32: add macros for machdep flags about ppc32 pte ppc32: add special vtop for FSL BOOKE ppc32: Ignore PMD ppc32: fixup vtop display items ppc32: fix page flags setup macro defs.h | 10 ++++ ppc.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 143 insertions(+), 29 deletions(-)
Date: Wed, 21 Mar 2012 13:58:06 +0900 Subject: [PATCH 1/5] ppc32: add macros for machdep flags about ppc32 pte Add IS_PAE() and IS_BOOKE() macros which can switch the way of page table translation. Signed-off-by: suzuki@xxxxxxxxxx Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- defs.h | 3 +++ ppc.c | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/defs.h b/defs.h index 2c8fae1..c742f21 100755 --- a/defs.h +++ b/defs.h @@ -2663,6 +2663,9 @@ struct machine_specific { ulong _page_shared; }; +/* machdep flags for ppc32 specific */ +#define IS_PAE() (machdep->flags & PAE) +#define IS_BOOKE() (machdep->flags & CPU_BOOKE) /* Page translation bits */ #define PPC_PLATFORM (machdep->machspec->platform) #define PTE_SIZE (machdep->machspec->pte_size) diff --git a/ppc.c b/ppc.c index 7037207..17d4218 100755 --- a/ppc.c +++ b/ppc.c @@ -118,7 +118,7 @@ probe_ppce500_platform(char *name) { if (STRNEQ(name, "ppce500mc")) { PPC_PLATFORM = strdup(name); - if (machdep->flags & PAE) { + if (IS_PAE()) { PTE_RPN_SHIFT = BOOKE3E_PTE_RPN_SHIFT; PLATFORM_PAGE_FLAGS_SETUP(BOOK3E); } else @@ -132,7 +132,7 @@ probe_ppce500_platform(char *name) static int probe_default_platform(char *name) { - if (machdep->flags & PAE) { + if (IS_PAE()) { error(INFO, "platform \"%s\" 64bit PTE fall through\n", name); error(INFO, "vmalloc translation could not work!\n"); } @@ -326,9 +326,9 @@ ppc_dump_machdep_table(ulong arg) fprintf(fp, " flags: %lx (", machdep->flags); if (machdep->flags & KSYMS_START) fprintf(fp, "%sKSYMS_START", others++ ? "|" : ""); - if (machdep->flags & PAE) + if (IS_PAE()) fprintf(fp, "%sPAE", others++ ? "|" : ""); - if (machdep->flags & CPU_BOOKE) + if (IS_BOOKE()) fprintf(fp, "%sCPU_BOOKE", others++ ? "|" : ""); fprintf(fp, ")\n"); @@ -428,7 +428,7 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) page_middle = (ulong *)pgd_pte; - if (machdep->flags & CPU_BOOKE) + if (IS_BOOKE()) page_table = (ulong *)((ulong)page_middle + ((ulong)BTOP(vaddr) & (PTRS_PER_PTE - 1)) * PTE_SIZE); else { page_table = (ulong *)((pgd_pte & (ulong)machdep->pagemask) + machdep->kvbase); @@ -440,7 +440,7 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) (ulong)page_table); FILL_PTBL(PAGEBASE((ulong)page_table), KVADDR, PAGESIZE()); - if (machdep->flags & PAE) + if (IS_PAE()) pte = ULONGLONG(machdep->ptbl + PAGEOFFSET((ulong)page_table)); else /* Defaults to ulong */ @@ -782,7 +782,7 @@ ppc_translate_pte(ulong pte32, void *physaddr, ulonglong pte64) char *arglist[MAXARGS]; ulonglong paddr; - if (!(machdep->flags & PAE)) + if (!IS_PAE()) pte64 = pte32; paddr = PAGEBASE(pte64); -- 1.7.0.4
Date: Wed, 21 Mar 2012 15:50:28 +0900 Subject: [PATCH 2/5] ppc32: add special vtop for FSL BOOKE FSL BOOKE MMU architecture own special address translation with TLBCAM which do not require the basic page table setup for memory access. Since the most kernel virtual address is set as TLBCAM region, those vtop can not resolve physical address from basic ppc vtop routine. Try to resolve it via TLBCAM if pgd entry is null. [before] kvtop failed because of no page table crash> vtop c0000000 VIRTUAL PHYSICAL c0000000 0 PAGE DIRECTORY: c08d1000 PGD: c08d2800 => 0 PAGE PHYSICAL MAPPING INDEX CNT FLAGS d0000000 0 0 0 1 400 [after] kvtop search from TLBCAM if mapped crash> vtop c0000000 VIRTUAL PHYSICAL c0000000 0 PAGE DIRECTORY: c08d1000 PGD: c08d2800 => 0 TLBCAM[0]: MAS0 MAS1 MAS2 MAS3 MAS7 10000001 c0000900 c0000004 15 0 VIRTUAL RANGE : c0000000 - cfffffff PHYSICAL RANGE: 0 - fffffff => VIRTUAL PHYSICAL TLBCAM-OFFSET c0000000 0 0 PAGE PHYSICAL MAPPING INDEX CNT FLAGS d0000000 0 0 0 1 400 Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- defs.h | 7 ++++ ppc.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 118 insertions(+), 1 deletions(-) diff --git a/defs.h b/defs.h index c742f21..a3a40e0 100755 --- a/defs.h +++ b/defs.h @@ -2661,6 +2661,10 @@ struct machine_specific { ulong _page_accessed; ulong _page_hwwrite; ulong _page_shared; + + /* platform special vtop */ + int (*vtop_special)(ulong vaddr, physaddr_t *paddr, int verbose); + void *mmu_special; }; /* machdep flags for ppc32 specific */ @@ -2676,6 +2680,9 @@ struct machine_specific { #define PGDIR_SHIFT (PAGE_SHIFT + PTE_SHIFT) #define PTRS_PER_PGD (1 << (32 - PGDIR_SHIFT)) #define PTRS_PER_PTE (1 << PTE_SHIFT) +/* special vtop */ +#define VTOP_SPECIAL (machdep->machspec->vtop_special) +#define MMU_SPECIAL (machdep->machspec->mmu_special) /* PFN shifts */ #define BOOKE3E_PTE_RPN_SHIFT (24) diff --git a/ppc.c b/ppc.c index 17d4218..11fe22f 100755 --- a/ppc.c +++ b/ppc.c @@ -113,6 +113,107 @@ probe_ppc44x_platform(char *name) return FALSE; } +struct fsl_booke_tlbcam { +#define NUM_TLBCAMS (64) +#define LAST_TLBCAM (0x40) + uint index; + struct { + ulong start; + ulong limit; + physaddr_t phys; + } tlbcamrange; + struct { + uint MAS0; + uint MAS1; + ulong MAS2; + uint MAS3; + uint MAS7; + } tlbcam; +}; + +static int +fsl_booke_vtop(ulong vaddr, physaddr_t *paddr, int verbose) +{ + struct fsl_booke_tlbcam *fsl_mmu; + int i, found; + + if (CRASHDEBUG(1)) + fprintf(fp, "[Searching tlbcam address mapping]\n"); + fsl_mmu = MMU_SPECIAL; + for (i = 0, found = FALSE;;i++, fsl_mmu++) { + if (vaddr >= fsl_mmu->tlbcamrange.start && + vaddr < fsl_mmu->tlbcamrange.limit) { + *paddr = fsl_mmu->tlbcamrange.phys + + (vaddr - fsl_mmu->tlbcamrange.start); + found = TRUE; + break; + } + if (fsl_mmu->index & LAST_TLBCAM) + break; + } + if (found && verbose) { + /* TLBCAM segment attributes */ + fprintf(fp, "\n TLBCAM[%u]: MAS0 MAS1 MAS2 " + "MAS3 MAS7\n", + (fsl_mmu->index & ~LAST_TLBCAM)); + fprintf(fp, " %-8lx %-8lx %-8lx %-8lx %-8lx\n", + fsl_mmu->tlbcam.MAS0, fsl_mmu->tlbcam.MAS1, + fsl_mmu->tlbcam.MAS2, fsl_mmu->tlbcam.MAS3, + fsl_mmu->tlbcam.MAS7); + /* TLBCAM range */ + fprintf(fp, " VIRTUAL RANGE : %lx - %lx\n", + fsl_mmu->tlbcamrange.start, fsl_mmu->tlbcamrange.limit); + fprintf(fp, " PHYSICAL RANGE: %llx - %llx\n", + fsl_mmu->tlbcamrange.phys, + fsl_mmu->tlbcamrange.phys + (fsl_mmu->tlbcamrange.limit + - fsl_mmu->tlbcamrange.start)); + /* translated addr and its tlbcam's offset. */ + fprintf(fp, " => VIRTUAL PHYSICAL TLBCAM-OFFSET\n"); + fprintf(fp, " %-8lx %-8llx %lu\n", vaddr, *paddr, + vaddr - fsl_mmu->tlbcamrange.start); + } + if (CRASHDEBUG(1)) + fprintf(fp, "[tlbcam search end]\n"); + + return found; +} + +static void +fsl_booke_mmu_setup(void) +{ + struct fsl_booke_tlbcam *fsl_mmu; + uint i, tlbcam_index; + ulong tlbcam_addrs, TLBCAM; + + readmem(symbol_value("tlbcam_index"), KVADDR, &tlbcam_index, + sizeof(uint), "tlbcam_index", FAULT_ON_ERROR); + if (tlbcam_index != 0 && tlbcam_index < NUM_TLBCAMS) { + fsl_mmu = calloc(tlbcam_index, sizeof(*fsl_mmu)); + if (!fsl_mmu) { + error(FATAL, "fsl_mmu calloc() failed\n"); + return; + } + tlbcam_addrs = symbol_value("tlbcam_addrs"); + TLBCAM = symbol_value("TLBCAM"); + for (i = 0; i < tlbcam_index; i++) { + fsl_mmu[i].index = i; + readmem(tlbcam_addrs + + i * sizeof(fsl_mmu[i].tlbcamrange), + KVADDR, &fsl_mmu[i].tlbcamrange, + sizeof(fsl_mmu[i].tlbcamrange), "tlbcam_addrs", + FAULT_ON_ERROR); + readmem(TLBCAM + i * sizeof(fsl_mmu[i].tlbcam), KVADDR, + &fsl_mmu[i].tlbcam, sizeof(fsl_mmu[i].tlbcam), + "TLBCAM", FAULT_ON_ERROR); + } + fsl_mmu[i - 1].index |= LAST_TLBCAM; + MMU_SPECIAL = fsl_mmu; + VTOP_SPECIAL = fsl_booke_vtop; + } else + error(INFO, "[%s]: can't setup tlbcam: tlbcam_index=%u\n", + PPC_PLATFORM, tlbcam_index); +} + static int probe_ppce500_platform(char *name) { @@ -123,6 +224,7 @@ probe_ppce500_platform(char *name) PLATFORM_PAGE_FLAGS_SETUP(BOOK3E); } else PLATFORM_PAGE_FLAGS_SETUP(FSL_BOOKE); + fsl_booke_mmu_setup(); return TRUE; } @@ -423,8 +525,16 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) if (verbose) fprintf(fp, " PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte); - if (!pgd_pte) + if (!pgd_pte) { + if (VTOP_SPECIAL) + /* + * This ppc platform have special address mapping + * between vaddr and paddr which can not search from + * standard page table. + */ + return VTOP_SPECIAL(vaddr, paddr, verbose); goto no_page; + } page_middle = (ulong *)pgd_pte; -- 1.7.0.4
Date: Thu, 22 Mar 2012 11:26:44 +0900 Subject: [PATCH 3/5] ppc32: Ignore PMD >From linux/arch/powerpc/include/asm/pgtable-ppc32.h #include <asm-generic/pgtable-nopmd.h> All powerpc 32bit never use pmd because that is the same shift value as pgd. I'm not sure whether PMD model was presence in powerpc 32bit... But at least, there is no more virtual address bits to provide for PMD then cleanup verbose message. [before] PMD translation is being done with page-shift & PTRS_PER_PTE where is conventionally for PTE. crash> vtop f99b77fc VIRTUAL PHYSICAL f99b77fc ffa417fc PAGE DIRECTORY: c08d1000 PGD: c08d2f30 => eb151000 PMD: eb151000 => eb151db8 PTE: eb151db8 => ffa41241255 PAGE: ffa41241000 PTE PHYSICAL FLAGS ffa41241255 ffa41241000 (PRESENT|RW|NO_CACHE) [after] Directly do PTE translation from PGD. crash> vtop f99b77fc VIRTUAL PHYSICAL f99b77fc ffa417fc PAGE DIRECTORY: c08d1000 PGD: c08d2f30 => eb151000 PTE: eb151000 => ffa41241255 PAGE: ffa41241000 PTE PHYSICAL FLAGS ffa41241255 ffa41241000 (PRESENT|RW|NO_CACHE) Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 28 +++++++++------------------- 1 files changed, 9 insertions(+), 19 deletions(-) diff --git a/ppc.c b/ppc.c index 11fe22f..dca19b7 100755 --- a/ppc.c +++ b/ppc.c @@ -504,9 +504,7 @@ static int ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) { ulong *page_dir; - ulong *page_middle; - ulong *page_table; - ulong pgd_pte; + ulong pgd_pte, page_table, pte_index; ulonglong pte; if (verbose) @@ -536,28 +534,20 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) goto no_page; } - page_middle = (ulong *)pgd_pte; - + page_table = pgd_pte; if (IS_BOOKE()) - page_table = (ulong *)((ulong)page_middle + ((ulong)BTOP(vaddr) & (PTRS_PER_PTE - 1)) * PTE_SIZE); - else { - page_table = (ulong *)((pgd_pte & (ulong)machdep->pagemask) + machdep->kvbase); - page_table = (ulong *)((ulong)page_table + ((ulong)BTOP(vaddr) & (PTRS_PER_PTE-1)) * PTE_SIZE); - } + page_table = VTOP(page_table); - if (verbose) - fprintf(fp, " PMD: %lx => %lx\n", (ulong)page_middle, - (ulong)page_table); - - FILL_PTBL(PAGEBASE((ulong)page_table), KVADDR, PAGESIZE()); + FILL_PTBL(PAGEBASE((ulong)page_table), PHYSADDR, PAGESIZE()); + pte_index = (vaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); if (IS_PAE()) - pte = ULONGLONG(machdep->ptbl + PAGEOFFSET((ulong)page_table)); + pte = ULONGLONG(machdep->ptbl + PTE_SIZE * pte_index); - else /* Defaults to ulong */ - pte = ULONG(machdep->ptbl + PAGEOFFSET((ulong)page_table)); + else + pte = ULONG(machdep->ptbl + PTE_SIZE * pte_index); if (verbose) - fprintf(fp, " PTE: %lx => %llx\n", (ulong)page_table, pte); + fprintf(fp, " PTE: %lx => %llx\n", pgd_pte, pte); if (!(pte & _PAGE_PRESENT)) { if (pte && verbose) { -- 1.7.0.4
Date: Thu, 22 Mar 2012 15:02:58 +0900 Subject: [PATCH 4/5] ppc32: fixup vtop display items Should translate with RPN_SHIFT before vtop dispaly PAGE and PHYSICAL. Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ppc.c b/ppc.c index dca19b7..512bfdd 100755 --- a/ppc.c +++ b/ppc.c @@ -558,7 +558,7 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) } if (verbose) { - fprintf(fp, " PAGE: %llx\n\n", PAGEBASE(pte)); + fprintf(fp, " PAGE: %llx\n\n", PAGEBASE(ppc_pte_physaddr(pte))); ppc_translate_pte((ulong)pte, 0, pte); } @@ -885,7 +885,7 @@ ppc_translate_pte(ulong pte32, void *physaddr, ulonglong pte64) if (!IS_PAE()) pte64 = pte32; - paddr = PAGEBASE(pte64); + paddr = PAGEBASE(ppc_pte_physaddr(pte64)); page_present = (pte64 & _PAGE_PRESENT); if (physaddr) { -- 1.7.0.4
Date: Thu, 22 Mar 2012 17:07:11 +0900 Subject: [PATCH 5/5] ppc32: fix page flags setup macro Must append do-while. Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx> --- ppc.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/ppc.c b/ppc.c index 512bfdd..8d54fff 100755 --- a/ppc.c +++ b/ppc.c @@ -88,6 +88,7 @@ probe_func_t probe_platforms[] = { /* Don't forget page flags definitions for each platform */ #define PLATFORM_PAGE_FLAGS_SETUP(PLT) \ +do { \ _PAGE_PRESENT = PLT##_PAGE_PRESENT; \ _PAGE_USER = PLT##_PAGE_USER; \ _PAGE_RW = PLT##_PAGE_RW; \ @@ -98,7 +99,9 @@ probe_func_t probe_platforms[] = { _PAGE_DIRTY = PLT##_PAGE_DIRTY; \ _PAGE_ACCESSED = PLT##_PAGE_ACCESSED; \ _PAGE_HWWRITE = PLT##_PAGE_HWWRITE; \ - _PAGE_SHARED = PLT##_PAGE_SHARED; + _PAGE_SHARED = PLT##_PAGE_SHARED; \ +} while (0) + static int probe_ppc44x_platform(char *name) { -- 1.7.0.4
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility