Message ID | 1507546335-27120-1-git-send-email-mpe@ellerman.id.au (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | [v3] powerpc/xmon: Support dumping software pagetables | expand |
Hi Balbir, [auto build test ERROR on powerpc/next] [also build test ERROR on v4.14-rc4 next-20171009] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Michael-Ellerman/powerpc-xmon-Support-dumping-software-pagetables/20171012-124024 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: powerpc-ppc64e_defconfig (attached as .config) compiler: powerpc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=powerpc All error/warnings (new ones prefixed by >>): In file included from arch/powerpc/include/asm/nohash/pgtable.h:5:0, from arch/powerpc/include/asm/pgtable.h:18, from include/linux/memremap.h:7, from include/linux/mm.h:26, from arch/powerpc/xmon/xmon.c:18: arch/powerpc/xmon/xmon.c: In function 'show_pte': >> arch/powerpc/include/asm/nohash/64/pgtable.h:158:40: error: right shift count >= width of type [-Werror=shift-count-overflow] #define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD - 1)) ^ >> arch/powerpc/include/asm/nohash/64/pgtable.h:160:47: note: in expansion of macro 'pgd_index' #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) ^~~~~~~~~ >> arch/powerpc/include/asm/nohash/64/pgtable.h:173:31: note: in expansion of macro 'pgd_offset' #define pgd_offset_k(address) pgd_offset(&init_mm, address) ^~~~~~~~~~ >> arch/powerpc/xmon/xmon.c:2992:11: note: in expansion of macro 'pgd_offset_k' pgdir = pgd_offset_k(0); ^~~~~~~~~~~~ >> arch/powerpc/include/asm/nohash/64/pgtable.h:158:40: error: right shift count >= width of type [-Werror=shift-count-overflow] #define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD - 1)) ^ >> arch/powerpc/include/asm/nohash/64/pgtable.h:160:47: note: in expansion of macro 'pgd_index' #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) ^~~~~~~~~ >> arch/powerpc/xmon/xmon.c:2995:11: note: in expansion of macro 'pgd_offset' pgdir = pgd_offset(mm, 0); ^~~~~~~~~~ cc1: all warnings being treated as errors vim +/pgd_offset +173 arch/powerpc/include/asm/nohash/64/pgtable.h f281b5d5 arch/powerpc/include/asm/pgtable-ppc64.h Aneesh Kumar K.V 2015-12-01 153 f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 154 /* f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 155 * Find an entry in a page-table-directory. We combine the address region f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 156 * (the high order N bits) and the pgd portion of the address. f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 157 */ 0e5f35d0 arch/powerpc/include/asm/pgtable-ppc64.h Aneesh Kumar K.V 2013-04-28 @158 #define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD - 1)) f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 159 f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 @160 #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 161 f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 162 #define pmd_offset(pudp,addr) \ f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 163 (((pmd_t *) pud_page_vaddr(*(pudp))) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))) f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 164 f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 165 #define pte_offset_kernel(dir,addr) \ f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 166 (((pte_t *) pmd_page_vaddr(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 167 f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 168 #define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 169 #define pte_unmap(pte) do { } while(0) f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 170 f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 171 /* to find an entry in a kernel page-table-directory */ f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 172 /* This now only contains the vmalloc pages */ f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 @173 #define pgd_offset_k(address) pgd_offset(&init_mm, address) 78f1dbde arch/powerpc/include/asm/pgtable-ppc64.h Aneesh Kumar K.V 2012-09-10 174 extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr, 78f1dbde arch/powerpc/include/asm/pgtable-ppc64.h Aneesh Kumar K.V 2012-09-10 175 pte_t *ptep, unsigned long pte, int huge); f88df14b include/asm-powerpc/pgtable-ppc64.h David Gibson 2007-04-30 176 :::::: The code at line 173 was first introduced by commit :::::: f88df14b1f15cdeffa060580a40c1ce3e13bb79e [POWERPC] Remove arch/powerpc's dependence on asm-ppc/pg{alloc,table}.h :::::: TO: David Gibson <david@gibson.dropbear.id.au> :::::: CC: Paul Mackerras <paulus@samba.org> --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Balbir, [auto build test ERROR on powerpc/next] [also build test ERROR on v4.14-rc4 next-20171009] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Michael-Ellerman/powerpc-xmon-Support-dumping-software-pagetables/20171012-124024 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: powerpc-ppc6xx_defconfig (attached as .config) compiler: powerpc-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=powerpc All error/warnings (new ones prefixed by >>): In file included from arch/powerpc/include/asm/book3s/pgtable.h:7:0, from arch/powerpc/include/asm/pgtable.h:16, from include/linux/memremap.h:7, from include/linux/mm.h:26, from arch/powerpc/xmon/xmon.c:18: arch/powerpc/xmon/xmon.c: In function 'show_pte': >> arch/powerpc/include/asm/book3s/32/pgtable.h:282:13: error: implicit declaration of function 'kmap_atomic' [-Werror=implicit-function-declaration] ((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr)) ^ >> arch/powerpc/xmon/xmon.c:3042:9: note: in expansion of macro 'pte_offset_map' ptep = pte_offset_map(pmdp, addr); ^~~~~~~~~~~~~~ cc1: all warnings being treated as errors vim +/pte_offset_map +3042 arch/powerpc/xmon/xmon.c 3024 3025 printf("pudp @ 0x%016lx = 0x%016lx\n", pudp, pud_val(*pudp)); 3026 3027 pmdp = pmd_offset(pudp, addr); 3028 3029 if (pmd_none(*pmdp)) { 3030 printf("No valid PMD\n"); 3031 return; 3032 } 3033 3034 #ifdef CONFIG_HUGETLB_PAGE 3035 if (pmd_huge(*pmdp)) { 3036 format_pte(pmdp, pmd_val(*pmdp)); 3037 return; 3038 } 3039 #endif 3040 printf("pmdp @ 0x%016lx = 0x%016lx\n", pmdp, pmd_val(*pmdp)); 3041 > 3042 ptep = pte_offset_map(pmdp, addr); 3043 if (pte_none(*ptep)) { 3044 printf("no valid PTE\n"); 3045 return; 3046 } 3047 3048 format_pte(ptep, pte_val(*ptep)); 3049 3050 sync(); 3051 __delay(200); 3052 catch_memory_errors = 0; 3053 } 3054 static void show_tasks(void) 3055 { 3056 unsigned long tskv; 3057 struct task_struct *tsk = NULL; 3058 3059 printf(" task_struct ->thread.ksp PID PPID S P CMD\n"); 3060 3061 if (scanhex(&tskv)) 3062 tsk = (struct task_struct *)tskv; 3063 3064 if (setjmp(bus_error_jmp) != 0) { 3065 catch_memory_errors = 0; 3066 printf("*** Error dumping task %p\n", tsk); 3067 return; 3068 } 3069 3070 catch_memory_errors = 1; 3071 sync(); 3072 3073 if (tsk) 3074 show_task(tsk); 3075 else 3076 for_each_process(tsk) 3077 show_task(tsk); 3078 3079 sync(); 3080 __delay(200); 3081 catch_memory_errors = 0; 3082 } 3083 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Thu, 12 Oct 2017 18:20:39 +0800 kbuild test robot <lkp@intel.com> wrote: > Hi Balbir, > > [auto build test ERROR on powerpc/next] > [also build test ERROR on v4.14-rc4 next-20171009] > [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] > > url: https://github.com/0day-ci/linux/commits/Michael-Ellerman/powerpc-xmon-Support-dumping-software-pagetables/20171012-124024 > base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next > config: powerpc-ppc6xx_defconfig (attached as .config) > compiler: powerpc-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 > reproduce: > wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross > chmod +x ~/bin/make.cross > # save the attached .config to linux build tree > make.cross ARCH=powerpc > > All error/warnings (new ones prefixed by >>): > > In file included from arch/powerpc/include/asm/book3s/pgtable.h:7:0, > from arch/powerpc/include/asm/pgtable.h:16, > from include/linux/memremap.h:7, > from include/linux/mm.h:26, > from arch/powerpc/xmon/xmon.c:18: > arch/powerpc/xmon/xmon.c: In function 'show_pte': > >> arch/powerpc/include/asm/book3s/32/pgtable.h:282:13: error: implicit declaration of function 'kmap_atomic' [-Werror=implicit-function-declaration] > ((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr)) > ^ > >> arch/powerpc/xmon/xmon.c:3042:9: note: in expansion of macro 'pte_offset_map' > ptep = pte_offset_map(pmdp, addr); > ^~~~~~~~~~~~~~ for pte_offset_map() to work, we need linux/highmem.h to be included in xmon.c. Balbir Singh.
Michael Ellerman <mpe@ellerman.id.au> writes: > From: Balbir Singh <bsingharora@gmail.com> > > It would be nice to be able to dump page tables in a particular > context. > > eg: dumping vmalloc space: > > 0:mon> dv 0xd00037fffff00000 > pgd @ 0xc0000000017c0000 > pgdp @ 0xc0000000017c00d8 = 0x00000000f10b1000 > pudp @ 0xc0000000f10b13f8 = 0x00000000f10d0000 > pmdp @ 0xc0000000f10d1ff8 = 0x00000000f1102000 > ptep @ 0xc0000000f1102780 = 0xc0000000f1ba018e > Maps physical address = 0x00000000f1ba0000 > Flags = Accessed Dirty Read Write > > This patch does not replicate the complex code of dump_pagetable and > has no support for bolted linear mapping, thats why I've it's called > dump virtual page table support. The format of the PTE can be expanded > even further to add more useful information about the flags in the PTE > if required. > > Signed-off-by: Balbir Singh <bsingharora@gmail.com> > [mpe: Bike shed the output format, show the pgdir] > Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> > --- > arch/powerpc/xmon/xmon.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 111 insertions(+) > > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c > index a41392dec822..d84bead0ac28 100644 > --- a/arch/powerpc/xmon/xmon.c > +++ b/arch/powerpc/xmon/xmon.c > @@ -127,6 +127,7 @@ static void byterev(unsigned char *, int); > static void memex(void); > static int bsesc(void); > static void dump(void); > +static void show_pte(unsigned long); > static void prdump(unsigned long, long); > static int ppc_inst_dump(unsigned long, long, int); > static void dump_log_buf(void); > @@ -234,6 +235,7 @@ Commands:\n\ > #endif > "\ > dr dump stream of raw bytes\n\ > + dv dump virtual address translation \n\ > dt dump the tracing buffers (uses printk)\n\ > dtc dump the tracing buffers for current CPU (uses printk)\n\ > " > @@ -2639,6 +2641,9 @@ dump(void) > dump_log_buf(); > } else if (c == 'o') { > dump_opal_msglog(); > + } else if (c == 'v') { > + /* dump virtual to physical translation */ > + show_pte(adrs); > } else if (c == 'r') { > scanhex(&ndump); > if (ndump == 0) > @@ -2972,6 +2977,112 @@ static void show_task(struct task_struct *tsk) > tsk->comm); > } > > +void format_pte(void *ptep, unsigned long pte) > +{ > + printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte);; > + printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK); > + > + printf("Flags = %s%s%s%s%s\n", > + (pte & _PAGE_ACCESSED) ? "Accessed " : "", > + (pte & _PAGE_DIRTY) ? "Dirty " : "", > + (pte & _PAGE_READ) ? "Read " : "", > + (pte & _PAGE_WRITE) ? "Write " : "", > + (pte & _PAGE_EXEC) ? "Exec " : ""); > +} > + > +static void show_pte(unsigned long addr) > +{ > + unsigned long tskv = 0; > + struct task_struct *tsk = NULL; > + struct mm_struct *mm; > + pgd_t *pgdp, *pgdir; > + pud_t *pudp; > + pmd_t *pmdp; > + pte_t *ptep; > + > + if (!scanhex(&tskv)) > + mm = &init_mm; > + else > + tsk = (struct task_struct *)tskv; > + > + if (tsk == NULL) > + mm = &init_mm; > + else > + mm = tsk->active_mm; > + > + if (setjmp(bus_error_jmp) != 0) { > + catch_memory_errors = 0; > + printf("*** Error dumping pte for task %p\n", tsk); > + return; > + } > + > + catch_memory_errors = 1; > + sync(); > + > + if (mm == &init_mm) { > + pgdp = pgd_offset_k(addr); > + pgdir = pgd_offset_k(0); > + } else { > + pgdp = pgd_offset(mm, addr); > + pgdir = pgd_offset(mm, 0); > + } > + > + if (pgd_none(*pgdp)) { > + printf("no linux page table for address\n"); > + return; > + } > + > + printf("pgd @ 0x%016lx\n", pgdir); > + > + if (pgd_huge(*pgdp)) { > + format_pte(pgdp, pgd_val(*pgdp)); > + return; > + } > + printf("pgdp @ 0x%016lx = 0x%016lx\n", pgdp, pgd_val(*pgdp)); > + > + pudp = pud_offset(pgdp, addr); > + > + if (pud_none(*pudp)) { > + printf("No valid PUD\n"); > + return; > + } > + > +#ifdef CONFIG_HUGETLB_PAGE > + if (pud_huge(*pudp)) { > + format_pte(pudp, pud_val(*pudp)); > + return; > + } > +#endif For page table walking code we don't need to put #ifdef here. Also how should we handle address that we map at pmd level even if hugetlb page is disabled ? (kernel linear mapping). Also where do we handle THP mapping ? You may want to look at __find_linux_pte() to write a page table walking code. or better use the helper. -aneesh
On Mon, Oct 16, 2017 at 2:34 PM, Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> wrote: > Michael Ellerman <mpe@ellerman.id.au> writes: > >> From: Balbir Singh <bsingharora@gmail.com> >> >> It would be nice to be able to dump page tables in a particular >> context. >> >> eg: dumping vmalloc space: >> >> 0:mon> dv 0xd00037fffff00000 >> pgd @ 0xc0000000017c0000 >> pgdp @ 0xc0000000017c00d8 = 0x00000000f10b1000 >> pudp @ 0xc0000000f10b13f8 = 0x00000000f10d0000 >> pmdp @ 0xc0000000f10d1ff8 = 0x00000000f1102000 >> ptep @ 0xc0000000f1102780 = 0xc0000000f1ba018e >> Maps physical address = 0x00000000f1ba0000 >> Flags = Accessed Dirty Read Write >> >> This patch does not replicate the complex code of dump_pagetable and >> has no support for bolted linear mapping, thats why I've it's called >> dump virtual page table support. The format of the PTE can be expanded >> even further to add more useful information about the flags in the PTE >> if required. >> >> Signed-off-by: Balbir Singh <bsingharora@gmail.com> >> [mpe: Bike shed the output format, show the pgdir] >> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> >> --- >> arch/powerpc/xmon/xmon.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 111 insertions(+) >> >> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c >> index a41392dec822..d84bead0ac28 100644 >> --- a/arch/powerpc/xmon/xmon.c >> +++ b/arch/powerpc/xmon/xmon.c >> @@ -127,6 +127,7 @@ static void byterev(unsigned char *, int); >> static void memex(void); >> static int bsesc(void); >> static void dump(void); >> +static void show_pte(unsigned long); >> static void prdump(unsigned long, long); >> static int ppc_inst_dump(unsigned long, long, int); >> static void dump_log_buf(void); >> @@ -234,6 +235,7 @@ Commands:\n\ >> #endif >> "\ >> dr dump stream of raw bytes\n\ >> + dv dump virtual address translation \n\ >> dt dump the tracing buffers (uses printk)\n\ >> dtc dump the tracing buffers for current CPU (uses printk)\n\ >> " >> @@ -2639,6 +2641,9 @@ dump(void) >> dump_log_buf(); >> } else if (c == 'o') { >> dump_opal_msglog(); >> + } else if (c == 'v') { >> + /* dump virtual to physical translation */ >> + show_pte(adrs); >> } else if (c == 'r') { >> scanhex(&ndump); >> if (ndump == 0) >> @@ -2972,6 +2977,112 @@ static void show_task(struct task_struct *tsk) >> tsk->comm); >> } >> >> +void format_pte(void *ptep, unsigned long pte) >> +{ >> + printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte);; >> + printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK); >> + >> + printf("Flags = %s%s%s%s%s\n", >> + (pte & _PAGE_ACCESSED) ? "Accessed " : "", >> + (pte & _PAGE_DIRTY) ? "Dirty " : "", >> + (pte & _PAGE_READ) ? "Read " : "", >> + (pte & _PAGE_WRITE) ? "Write " : "", >> + (pte & _PAGE_EXEC) ? "Exec " : ""); >> +} >> + >> +static void show_pte(unsigned long addr) >> +{ >> + unsigned long tskv = 0; >> + struct task_struct *tsk = NULL; >> + struct mm_struct *mm; >> + pgd_t *pgdp, *pgdir; >> + pud_t *pudp; >> + pmd_t *pmdp; >> + pte_t *ptep; >> + >> + if (!scanhex(&tskv)) >> + mm = &init_mm; >> + else >> + tsk = (struct task_struct *)tskv; >> + >> + if (tsk == NULL) >> + mm = &init_mm; >> + else >> + mm = tsk->active_mm; >> + >> + if (setjmp(bus_error_jmp) != 0) { >> + catch_memory_errors = 0; >> + printf("*** Error dumping pte for task %p\n", tsk); >> + return; >> + } >> + >> + catch_memory_errors = 1; >> + sync(); >> + >> + if (mm == &init_mm) { >> + pgdp = pgd_offset_k(addr); >> + pgdir = pgd_offset_k(0); >> + } else { >> + pgdp = pgd_offset(mm, addr); >> + pgdir = pgd_offset(mm, 0); >> + } >> + >> + if (pgd_none(*pgdp)) { >> + printf("no linux page table for address\n"); >> + return; >> + } >> + >> + printf("pgd @ 0x%016lx\n", pgdir); >> + >> + if (pgd_huge(*pgdp)) { >> + format_pte(pgdp, pgd_val(*pgdp)); >> + return; >> + } >> + printf("pgdp @ 0x%016lx = 0x%016lx\n", pgdp, pgd_val(*pgdp)); >> + >> + pudp = pud_offset(pgdp, addr); >> + >> + if (pud_none(*pudp)) { >> + printf("No valid PUD\n"); >> + return; >> + } >> + >> +#ifdef CONFIG_HUGETLB_PAGE >> + if (pud_huge(*pudp)) { >> + format_pte(pudp, pud_val(*pudp)); >> + return; >> + } >> +#endif > > For page table walking code we don't need to put #ifdef here. OK.. I designed this for both, I'll take the #ifdef out for kernel page tables. Also how > should we handle address that we map at pmd level even if hugetlb page > is disabled ? (kernel linear mapping). Also where do we handle THP > mapping ? You may want to look at __find_linux_pte() to write a page > table walking code. or better use the helper. I wanted to avoid using __find_linux_pte in xmon(), it needs irq's disabled. I found the interface a bit cumbersome. If I fix the #ifdef's and make the walking code 64 bit only I think we should be OK? Do you agree? Balbir Singh. > > -aneesh >
On 10/16/2017 10:43 AM, Balbir Singh wrote: > On Mon, Oct 16, 2017 at 2:34 PM, Aneesh Kumar K.V > <aneesh.kumar@linux.vnet.ibm.com> wrote: >> Michael Ellerman <mpe@ellerman.id.au> writes: >>> + >>> +#ifdef CONFIG_HUGETLB_PAGE >>> + if (pud_huge(*pudp)) { >>> + format_pte(pudp, pud_val(*pudp)); >>> + return; >>> + } >>> +#endif >> >> For page table walking code we don't need to put #ifdef here. > > OK.. I designed this for both, I'll take the #ifdef out for kernel page tables. > > Also how >> should we handle address that we map at pmd level even if hugetlb page >> is disabled ? (kernel linear mapping). Also where do we handle THP >> mapping ? You may want to look at __find_linux_pte() to write a page >> table walking code. or better use the helper. > > I wanted to avoid using __find_linux_pte in xmon(), it needs irq's disabled. > I found the interface a bit cumbersome. If I fix the #ifdef's and make the > walking code 64 bit only I think we should be OK? Do you agree? > __find_linux_pte doesn't require irq disabled. But i would suggest we add a comment there explaining why it is safe to use without being worried about irqs/THP split (ex: find_init_mm_pte()). Being in xmon we are safe there. We moved all the warning about irq disabled etc to higher level functions. -aneesh
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index a41392dec822..d84bead0ac28 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -127,6 +127,7 @@ static void byterev(unsigned char *, int); static void memex(void); static int bsesc(void); static void dump(void); +static void show_pte(unsigned long); static void prdump(unsigned long, long); static int ppc_inst_dump(unsigned long, long, int); static void dump_log_buf(void); @@ -234,6 +235,7 @@ Commands:\n\ #endif "\ dr dump stream of raw bytes\n\ + dv dump virtual address translation \n\ dt dump the tracing buffers (uses printk)\n\ dtc dump the tracing buffers for current CPU (uses printk)\n\ " @@ -2639,6 +2641,9 @@ dump(void) dump_log_buf(); } else if (c == 'o') { dump_opal_msglog(); + } else if (c == 'v') { + /* dump virtual to physical translation */ + show_pte(adrs); } else if (c == 'r') { scanhex(&ndump); if (ndump == 0) @@ -2972,6 +2977,112 @@ static void show_task(struct task_struct *tsk) tsk->comm); } +void format_pte(void *ptep, unsigned long pte) +{ + printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte);; + printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK); + + printf("Flags = %s%s%s%s%s\n", + (pte & _PAGE_ACCESSED) ? "Accessed " : "", + (pte & _PAGE_DIRTY) ? "Dirty " : "", + (pte & _PAGE_READ) ? "Read " : "", + (pte & _PAGE_WRITE) ? "Write " : "", + (pte & _PAGE_EXEC) ? "Exec " : ""); +} + +static void show_pte(unsigned long addr) +{ + unsigned long tskv = 0; + struct task_struct *tsk = NULL; + struct mm_struct *mm; + pgd_t *pgdp, *pgdir; + pud_t *pudp; + pmd_t *pmdp; + pte_t *ptep; + + if (!scanhex(&tskv)) + mm = &init_mm; + else + tsk = (struct task_struct *)tskv; + + if (tsk == NULL) + mm = &init_mm; + else + mm = tsk->active_mm; + + if (setjmp(bus_error_jmp) != 0) { + catch_memory_errors = 0; + printf("*** Error dumping pte for task %p\n", tsk); + return; + } + + catch_memory_errors = 1; + sync(); + + if (mm == &init_mm) { + pgdp = pgd_offset_k(addr); + pgdir = pgd_offset_k(0); + } else { + pgdp = pgd_offset(mm, addr); + pgdir = pgd_offset(mm, 0); + } + + if (pgd_none(*pgdp)) { + printf("no linux page table for address\n"); + return; + } + + printf("pgd @ 0x%016lx\n", pgdir); + + if (pgd_huge(*pgdp)) { + format_pte(pgdp, pgd_val(*pgdp)); + return; + } + printf("pgdp @ 0x%016lx = 0x%016lx\n", pgdp, pgd_val(*pgdp)); + + pudp = pud_offset(pgdp, addr); + + if (pud_none(*pudp)) { + printf("No valid PUD\n"); + return; + } + +#ifdef CONFIG_HUGETLB_PAGE + if (pud_huge(*pudp)) { + format_pte(pudp, pud_val(*pudp)); + return; + } +#endif + + printf("pudp @ 0x%016lx = 0x%016lx\n", pudp, pud_val(*pudp)); + + pmdp = pmd_offset(pudp, addr); + + if (pmd_none(*pmdp)) { + printf("No valid PMD\n"); + return; + } + +#ifdef CONFIG_HUGETLB_PAGE + if (pmd_huge(*pmdp)) { + format_pte(pmdp, pmd_val(*pmdp)); + return; + } +#endif + printf("pmdp @ 0x%016lx = 0x%016lx\n", pmdp, pmd_val(*pmdp)); + + ptep = pte_offset_map(pmdp, addr); + if (pte_none(*ptep)) { + printf("no valid PTE\n"); + return; + } + + format_pte(ptep, pte_val(*ptep)); + + sync(); + __delay(200); + catch_memory_errors = 0; +} static void show_tasks(void) { unsigned long tskv;