Hi Baoquan,

Sorry for the late reply.

The patch looks good.


Thanks
Tachibana

> -----Original Message-----
> From: kexec [mailto:kexec-boun...@lists.infradead.org] On Behalf Of Baoquan He
> Sent: Friday, March 02, 2018 2:49 PM
> To: kexec@lists.infradead.org
> Cc: douly.f...@cn.fujitsu.com; indou.ta...@jp.fujitsu.com; Hayashi Masahiko() 
> <mas-haya...@tg.jp.nec.com>;
> Tachibana Masaki() <mas-tachib...@vf.jp.nec.com>
> Subject: [PATCH 4/4] arch/x86_64: Add 5-level paging support
> 
> From: Dou Liyang <douly.f...@cn.fujitsu.com>
> 
> Now, kernel can use 5-level page tables in x86_64 system.
> 
> Add the 5-level paging support for makedumpfile.
> 
> Signed-off-by: Dou Liyang <douly.f...@cn.fujitsu.com>
> ---
>  arch/x86_64.c  | 76 
> ++++++++++++++++++++++++++++++++++++++++++----------------
>  makedumpfile.h | 17 +++++++++++++
>  2 files changed, 72 insertions(+), 21 deletions(-)
> 
> diff --git a/arch/x86_64.c b/arch/x86_64.c
> index e88ee0b..b242f36 100644
> --- a/arch/x86_64.c
> +++ b/arch/x86_64.c
> @@ -112,6 +112,8 @@ get_page_offset_x86_64(void)
> 
>       if (info->kernel_version < KERNEL_VERSION(2, 6, 27)) {
>               info->page_offset = __PAGE_OFFSET_ORIG;
> +     } else if(check_5level_paging()) {
> +             info->page_offset = __PAGE_OFFSET_5LEVEL;
>       } else {
>               info->page_offset = __PAGE_OFFSET_2_6_27;
>       }
> @@ -243,6 +245,8 @@ get_versiondep_info_x86_64(void)
>               info->max_physmem_bits  = _MAX_PHYSMEM_BITS_ORIG;
>       else if (info->kernel_version < KERNEL_VERSION(2, 6, 31))
>               info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_26;
> +     else if(check_5level_paging())
> +             info->max_physmem_bits  = _MAX_PHYSMEM_BITS_5LEVEL;
>       else
>               info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_31;
> 
> @@ -252,6 +256,9 @@ get_versiondep_info_x86_64(void)
>       if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
>               info->vmemmap_start = VMEMMAP_START_ORIG;
>               info->vmemmap_end   = VMEMMAP_END_ORIG;
> +     } else if(check_5level_paging()) {
> +             info->vmemmap_start = VMEMMAP_START_5LEVEL;
> +             info->vmemmap_end   = VMEMMAP_END_5LEVEL;
>       } else {
>               info->vmemmap_start = VMEMMAP_START_2_6_31;
>               info->vmemmap_end   = VMEMMAP_END_2_6_31;
> @@ -268,6 +275,7 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long 
> pagetable)
>  {
>       unsigned long page_dir, pgd, pud_paddr, pud_pte, pmd_paddr, pmd_pte;
>       unsigned long pte_paddr, pte;
> +     unsigned long p4d_paddr, p4d_pte;
> 
>       /*
>        * Get PGD.
> @@ -278,23 +286,56 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long 
> pagetable)
>               if (page_dir == NOT_PADDR)
>                       return NOT_PADDR;
>       }
> -     page_dir += pgd_index(vaddr) * sizeof(unsigned long);
> -     if (!readmem(PADDR, page_dir, &pgd, sizeof pgd)) {
> -             ERRMSG("Can't get pgd (page_dir:%lx).\n", page_dir);
> -             return NOT_PADDR;
> -     }
> -     if (info->vaddr_for_vtop == vaddr)
> -             MSG("  PGD : %16lx => %16lx\n", page_dir, pgd);
> 
> -     if (!(pgd & _PAGE_PRESENT)) {
> -             ERRMSG("Can't get a valid pgd.\n");
> -             return NOT_PADDR;
> +     if (check_5level_paging()) {
> +             page_dir += pgd5_index(vaddr) * sizeof(unsigned long);
> +             if (!readmem(PADDR, page_dir, &pgd, sizeof pgd)) {
> +                     ERRMSG("Can't get pgd (page_dir:%lx).\n", page_dir);
> +                     return NOT_PADDR;
> +             }
> +             if (info->vaddr_for_vtop == vaddr)
> +                     MSG("  PGD : %16lx => %16lx\n", page_dir, pgd);
> +
> +             if (!(pgd & _PAGE_PRESENT)) {
> +                     ERRMSG("Can't get a valid pgd.\n");
> +                     return NOT_PADDR;
> +             }
> +             /*
> +              * Get P4D.
> +              */
> +             p4d_paddr  = pgd & ENTRY_MASK;
> +             p4d_paddr += p4d_index(vaddr) * sizeof(unsigned long);
> +             if (!readmem(PADDR, p4d_paddr, &p4d_pte, sizeof p4d_pte)) {
> +                     ERRMSG("Can't get p4d_pte (p4d_paddr:%lx).\n", 
> p4d_paddr);
> +                     return NOT_PADDR;
> +             }
> +             if (info->vaddr_for_vtop == vaddr)
> +                     MSG("  P4D : %16lx => %16lx\n", p4d_paddr, p4d_pte);
> +
> +             if (!(p4d_pte & _PAGE_PRESENT)) {
> +                     ERRMSG("Can't get a valid p4d_pte.\n");
> +                     return NOT_PADDR;
> +             }
> +             pud_paddr  = p4d_pte & ENTRY_MASK;
> +     }else {
> +             page_dir += pgd_index(vaddr) * sizeof(unsigned long);
> +             if (!readmem(PADDR, page_dir, &pgd, sizeof pgd)) {
> +                     ERRMSG("Can't get pgd (page_dir:%lx).\n", page_dir);
> +                     return NOT_PADDR;
> +             }
> +             if (info->vaddr_for_vtop == vaddr)
> +                     MSG("  PGD : %16lx => %16lx\n", page_dir, pgd);
> +
> +             if (!(pgd & _PAGE_PRESENT)) {
> +                     ERRMSG("Can't get a valid pgd.\n");
> +                     return NOT_PADDR;
> +             }
> +             pud_paddr  = pgd & ENTRY_MASK;
>       }
> 
>       /*
>        * Get PUD.
>        */
> -     pud_paddr  = pgd & ENTRY_MASK;
>       pud_paddr += pud_index(vaddr) * sizeof(unsigned long);
>       if (!readmem(PADDR, pud_paddr, &pud_pte, sizeof pud_pte)) {
>               ERRMSG("Can't get pud_pte (pud_paddr:%lx).\n", pud_paddr);
> @@ -361,12 +402,7 @@ vtop4_x86_64(unsigned long vaddr)
>       else if (SYMBOL(init_top_pgt) != NOT_FOUND_SYMBOL)
>               init_level4_pgt = SYMBOL(init_top_pgt);
>       else {
> -             ERRMSG("Can't get the symbol of init_level4_pgt.\n");
> -             return NOT_PADDR;
> -     }
> -
> -     if (SYMBOL(level4_kernel_pgt) != NOT_FOUND_SYMBOL) {
> -             ERRMSG("Kernel is built with 5-level page tables\n");
> +             ERRMSG("Can't get the symbol of 
> init_level4_pgt/init_top_pgt.\n");
>               return NOT_PADDR;
>       }
> 
> @@ -605,10 +641,6 @@ find_vmemmap_x86_64()
>               return FAILED;
>       }
> 
> -     if (SYMBOL(level4_kernel_pgt) != NOT_FOUND_SYMBOL) {
> -             ERRMSG("kernel is configured for 5-level page tables\n");
> -             return FAILED;
> -     }
>       pagestructsize = size_table.page;
>       hugepagesize = PTRS_PER_PMD * info->page_size;
>       vaddr_base = info->vmemmap_start;
> @@ -630,12 +662,14 @@ find_vmemmap_x86_64()
>       /* outer loop is for pud entries in the pgd */
>       for (pgdindex = 0, pgdp = (unsigned long *)pgd_addr; pgdindex < 
> num_puds;
>                                                               pgdindex++, 
> pgdp++) {
> +
>               /* read the pgd one word at a time, into pud_addr */
>               if (!readmem(PADDR, (unsigned long long)pgdp, (void *)&pud_addr,
>                                                               sizeof(unsigned 
> long))) {
>                       ERRMSG("Can't get pgd entry for slot %d.\n", pgd_index);
>                       return FAILED;
>               }
> +
>               /* mask the pgd entry for the address of the pud page */
>               pud_addr &= PMASK;
>               if (pud_addr == 0)
> diff --git a/makedumpfile.h b/makedumpfile.h
> index a0d1c13..d26c30b 100644
> --- a/makedumpfile.h
> +++ b/makedumpfile.h
> @@ -581,16 +581,21 @@ unsigned long get_kvbase_arm64(void);
>  #ifdef __x86_64__
>  #define __PAGE_OFFSET_ORIG   (0xffff810000000000) /* 2.6.26, or former */
>  #define __PAGE_OFFSET_2_6_27 (0xffff880000000000) /* 2.6.27, or later  */
> +#define __PAGE_OFFSET_5LEVEL (0xff10000000000000) /* 5-level page table */
> 
>  #define VMALLOC_START_ORIG   (0xffffc20000000000) /* 2.6.30, or former */
>  #define VMALLOC_START_2_6_31 (0xffffc90000000000) /* 2.6.31, or later  */
> +#define VMALLOC_START_5LEVEL (0xffa0000000000000) /* 5-level page table */
>  #define VMALLOC_END_ORIG     (0xffffe1ffffffffff) /* 2.6.30, or former */
>  #define VMALLOC_END_2_6_31   (0xffffe8ffffffffff) /* 2.6.31, or later  */
> +#define VMALLOC_END_5LEVEL   (0xffd1ffffffffffff) /* 5-level page table */
> 
>  #define VMEMMAP_START_ORIG   (0xffffe20000000000) /* 2.6.30, or former */
>  #define VMEMMAP_START_2_6_31 (0xffffea0000000000) /* 2.6.31, or later  */
> +#define VMEMMAP_START_5LEVEL (0xffd4000000000000) /* 5-level page table */
>  #define VMEMMAP_END_ORIG     (0xffffe2ffffffffff) /* 2.6.30, or former */
>  #define VMEMMAP_END_2_6_31   (0xffffeaffffffffff) /* 2.6.31, or later  */
> +#define VMEMMAP_END_5LEVEL   (0xffd5ffffffffffff) /* 5-level page table */
> 
>  #define __START_KERNEL_map   (0xffffffff80000000)
>  #define KVBASE                       PAGE_OFFSET
> @@ -598,6 +603,7 @@ unsigned long get_kvbase_arm64(void);
>  #define _MAX_PHYSMEM_BITS_ORIG               (40)
>  #define _MAX_PHYSMEM_BITS_2_6_26     (44)
>  #define _MAX_PHYSMEM_BITS_2_6_31     (46)
> +#define _MAX_PHYSMEM_BITS_5LEVEL     (52)
> 
>  /*
>   * 4 Levels paging
> @@ -617,7 +623,18 @@ unsigned long get_kvbase_arm64(void);
>  #define PMD_SIZE             (1UL << PMD_SHIFT)
>  #define PMD_MASK             (~(PMD_SIZE - 1))
> 
> +/*
> + * 5 Levels paging
> + */
> +#define PGD_SHIFT_5LEVEL     (48)
> +#define P4D_SHIFT            (39)
> +
> +#define PTRS_PER_PGD_5LEVEL  (512)
> +#define PTRS_PER_P4D         (512)
> +
> +#define pgd5_index(address)  (((address) >> PGD_SHIFT_5LEVEL) & 
> (PTRS_PER_PGD_5LEVEL - 1))
>  #define pgd_index(address)  (((address) >> PGD_SHIFT) & (PTRS_PER_PGD - 1))
> +#define p4d_index(address)  (((address) >> P4D_SHIFT) & (PTRS_PER_P4D - 1))
>  #define pud_index(address)  (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
>  #define pmd_index(address)  (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
>  #define pte_index(address)  (((address) >> PTE_SHIFT) & (PTRS_PER_PTE - 1))
> --
> 2.13.6
> 
> 
> _______________________________________________
> kexec mailing list
> kexec@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to