[PATCH v2 2/2] makedumpfile: vtop address translation support for vmalloc region in PPC64 arch
Atsushi Kumagai
kumagai-atsushi at mxc.nes.nec.co.jp
Wed Aug 6 16:50:50 PDT 2014
>This patch adds virtual to physical address translation support
>for vmalloc region in PPC64 architecture.
>
>Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com>
>---
> arch/ppc64.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++-------
> makedumpfile.h | 3 ++
> 2 files changed, 91 insertions(+), 12 deletions(-)
>
>diff --git a/arch/ppc64.c b/arch/ppc64.c
>index 8c7eaa7..8bb90d9 100644
>--- a/arch/ppc64.c
>+++ b/arch/ppc64.c
>@@ -24,6 +24,8 @@
> #include "../elf_info.h"
> #include "../makedumpfile.h"
>
>+static char *page_buf; /* Page buffer to read page tables */
>+
> /*
> * This function traverses vmemmap list to get the count of vmemmap regions
> * and populates the regions' info in info->vmemmap_list[]
>@@ -224,6 +226,83 @@ ppc64_vmemmap_to_phys(unsigned long vaddr)
> return paddr;
> }
>
>+static unsigned long long
>+ppc64_vtop_level4(unsigned long vaddr)
>+{
>+ ulong *level4, *level4_dir;
>+ ulong *page_dir, *page_middle;
>+ ulong *page_table;
>+ unsigned long long level4_pte, pgd_pte;
>+ unsigned long long pmd_pte, pte;
>+ unsigned long long paddr = NOT_PADDR;
>+
>+ if (page_buf == NULL) {
>+ /*
>+ * This is the first vmalloc address translation request
>+ */
>+ page_buf = (char *)calloc(1, PAGESIZE());
Hmm, the v2 way can't free this buffer at the appropriate time, sorry.
Could you put it back in struct DumpInfo like v1 and free it at the
end of main() ?
Thanks
Atsushi Kumagai
>+ if (page_buf == NULL) {
>+ ERRMSG("Can't allocate memory to read page tables. %s\n",
>+ strerror(errno));
>+ return NOT_PADDR;
>+ }
>+ }
>+
>+ level4 = (ulong *)info->kernel_pgd;
>+ level4_dir = (ulong *)((ulong *)level4 + L4_OFFSET(vaddr));
>+ if (!readmem(VADDR, PAGEBASE(level4), page_buf, PAGESIZE())) {
>+ ERRMSG("Can't read level4 page: 0x%llx\n", PAGEBASE(level4));
>+ return NOT_PADDR;
>+ }
>+ level4_pte = ULONG((page_buf + PAGEOFFSET(level4_dir)));
>+ if (!level4_pte)
>+ return NOT_PADDR;
>+
>+ /*
>+ * Sometimes we don't have level3 pagetable entries
>+ */
>+ if (info->l3_index_size != 0) {
>+ page_dir = (ulong *)((ulong *)level4_pte + PGD_OFFSET_L4(vaddr));
>+ if (!readmem(VADDR, PAGEBASE(level4_pte), page_buf, PAGESIZE())) {
>+ ERRMSG("Can't read PGD page: 0x%llx\n", PAGEBASE(level4_pte));
>+ return NOT_PADDR;
>+ }
>+ pgd_pte = ULONG((page_buf + PAGEOFFSET(page_dir)));
>+ if (!pgd_pte)
>+ return NOT_PADDR;
>+ } else {
>+ pgd_pte = level4_pte;
>+ }
>+
>+ page_middle = (ulong *)((ulong *)pgd_pte + PMD_OFFSET_L4(vaddr));
>+ if (!readmem(VADDR, PAGEBASE(pgd_pte), page_buf, PAGESIZE())) {
>+ ERRMSG("Can't read PMD page: 0x%llx\n", PAGEBASE(pgd_pte));
>+ return NOT_PADDR;
>+ }
>+ pmd_pte = ULONG((page_buf + PAGEOFFSET(page_middle)));
>+ if (!(pmd_pte))
>+ return NOT_PADDR;
>+
>+ page_table = (ulong *)(pmd_pte & ~(info->l2_masked_bits))
>+ + (BTOP(vaddr) & (info->ptrs_per_l1 - 1));
>+ if (!readmem(VADDR, PAGEBASE(pmd_pte), page_buf, PAGESIZE())) {
>+ ERRMSG("Can't read page table: 0x%llx\n", PAGEBASE(pmd_pte));
>+ return NOT_PADDR;
>+ }
>+ pte = ULONG((page_buf + PAGEOFFSET(page_table)));
>+ if (!(pte & _PAGE_PRESENT)) {
>+ ERRMSG("Page not present!\n");
>+ return NOT_PADDR;
>+ }
>+
>+ if (!pte)
>+ return NOT_PADDR;
>+
>+ paddr = PAGEBASE(PTOB(pte >> info->pte_shift)) + PAGEOFFSET(vaddr);
>+
>+ return paddr;
>+}
>+
> int
> set_ppc64_max_physmem_bits(void)
> {
>@@ -347,10 +426,18 @@ vaddr_to_paddr_ppc64(unsigned long vaddr)
> {
> unsigned long long paddr;
>
>+ if ((info->flag_vmemmap)
>+ && (vaddr >= info->vmemmap_start)) {
>+ return ppc64_vmemmap_to_phys(vaddr);
>+ }
>+
> paddr = vaddr_to_paddr_general(vaddr);
> if (paddr != NOT_PADDR)
> return paddr;
>
>+ if (!is_vmalloc_addr_ppc64(vaddr))
>+ return (vaddr - info->kernel_start);
>+
> if ((SYMBOL(vmap_area_list) == NOT_FOUND_SYMBOL)
> || (OFFSET(vmap_area.va_start) == NOT_FOUND_STRUCTURE)
> || (OFFSET(vmap_area.list) == NOT_FOUND_STRUCTURE)) {
>@@ -360,19 +447,8 @@ vaddr_to_paddr_ppc64(unsigned long vaddr)
> return NOT_PADDR;
> }
> }
>- if (!is_vmalloc_addr_ppc64(vaddr))
>- return (vaddr - info->kernel_start);
>
>- if ((info->flag_vmemmap)
>- && (vaddr >= info->vmemmap_start)) {
>- return ppc64_vmemmap_to_phys(vaddr);
>- }
>-
>- /*
>- * TODO: Support vmalloc translation.
>- */
>- ERRMSG("This makedumpfile does not support vmalloc translation.\n");
>- return NOT_PADDR;
>+ return ppc64_vtop_level4(vaddr);
> }
>
> #endif /* powerpc64 */
>diff --git a/makedumpfile.h b/makedumpfile.h
>index 8510b8f..dba3a0c 100644
>--- a/makedumpfile.h
>+++ b/makedumpfile.h
>@@ -158,6 +158,9 @@ isAnon(unsigned long mapping)
> return ((unsigned long)mapping & PAGE_MAPPING_ANON) != 0;
> }
>
>+#define PTOB(X) (((unsigned long long)(X)) << PAGESHIFT())
>+#define BTOP(X) (((unsigned long long)(X)) >> PAGESHIFT())
>+
> #define PAGESIZE() (info->page_size)
> #define PAGESHIFT() (info->page_shift)
> #define PAGEOFFSET(X) (((unsigned long long)(X)) & (PAGESIZE() - 1))
More information about the kexec
mailing list