ARM64: 3 Level page support
Subsystems (2)
cover ARM64: 3 Level page support
Hi Atsushi,
ARM64 was supporting only two level page support. These patches add support for 3 level page table as well.
~Pratyush
Pratyush Anand (3):
ARM64: Refactor code to support multiple page level
arm64: Decide VA Bits on the basis of _stext symbol value
arm64: Fix KVBASE
Sameer Goel (1):
arm64: Fix for ARM64 3 level translation tables
arch/arm64.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++------ makedumpfile.h | 29 +++------------- 2 files changed, 98 insertions(+), 34 deletions(-)
Signature · 7 lines
2.5.0 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH 1/4 ARM64: Refactor code to support multiple page level
This patch refactor existing code, so that multiple page level can be supported. No functional change. Platform dependent values like page table level, page shift and VA bits are still hard coded as 2, 16 and 42, to support 2 level 64K pages.
--- arch/arm64.c | 44 +++++++++++++++++++++++++++++++++++++++++--- makedumpfile.h | 26 ++++---------------------- 2 files changed, 45 insertions(+), 25 deletions(-)
arch/arm64.c +41 -3
@@ -23,7 +23,6 @@#include "../makedumpfile.h" #include "../print_info.h" -#if CONFIG_ARM64_PGTABLE_LEVELS ==2 typedef struct {unsigned long pgd; }pgd_t ;
@@ -45,8 +44,6 @@ typedef struct {#define PUD_SHIFT PGDIR_SHIFT#define PUD_SIZE (1UL << PUD_SHIFT) -#endif -typedef struct {unsigned long pte; }pte_t ;
@@ -96,6 +93,41 @@ typedef struct {#define MODULES_END PAGE_OFFSET#define MODULES_VADDR (MODULES_END - 0x4000000) +static int pgtable_level; +static int va_bits; +static int page_shift; + +int +get_pgtable_level_arm64 (void ) +{ +return pgtable_level; +} + +int +get_va_bits_arm64 (void ) +{ +return va_bits; +} + +int +get_page_shift_arm64 (void ) +{ +return page_shift; +} + +static int calculate_plat_config (void ) +{ +/* +* TODO: Keep it fixed for page level 2, size 64K and VA bits as +* 42, as of now. Will calculate them from symbol address values +* latter. +*/ + pgtable_level =2 ; + va_bits =42 ; + page_shift =16 ; + +return TRUE; +}static int is_vtop_from_page_table_arm64 (unsigned long vaddr)
@@ -114,6 +146,12 @@ get_phys_base_arm64(void)unsigned long phys_base =ULONG_MAX ;unsigned long long phys_start;int i; + +if (!calculate_plat_config ()) { +ERRMSG ("Can't determine platform config values\n" ); +return FALSE; + } +/* * We resolve phys_base from PT_LOAD segments. LMA contains physical * address of the segment, and we use the lowest start as
makedumpfile.h +4 -22
@@ -503,28 +503,10 @@ do { \#define PMASK (0x7ffffffffffff000UL)#ifdef __aarch64__ -#define CONFIG_ARM64_PGTABLE_LEVELS 2 -#define CONFIG_ARM64_VA_BITS 42 -#define CONFIG_ARM64_64K_PAGES 1 - -/* Currently we only suport following defines based on above -* config definitions. -* TODOs: We need to find a way to get above defines dynamically and -* then to support following definitions based on that -*/ - -#if CONFIG_ARM64_PGTABLE_LEVELS ==2 -#define ARM64_PGTABLE_LEVELS 2 -#endif - -#if CONFIG_ARM64_VA_BITS ==42 -#define VA_BITS 42 -#endif - -#ifdef CONFIG_ARM64_64K_PAGES -#define PAGE_SHIFT 16 -#endif - +int get_va_bits_arm64 (void ); +#define ARM64_PGTABLE_LEVELS get_pgtable_level_arm64() +#define VA_BITS get_va_bits_arm64() +#define PAGE_SHIFT get_page_shift_arm64()#define KVBASE_MASK (0xffffffffffffffffUL << (VA_BITS - 1))#define KVBASE (SYMBOL(_stext) & KVBASE_MASK)#endif /* aarch64 */
Signature · 7 lines
2.5.0 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH 3/4 arm64: Fix KVBASE
In reply to Pratyush AnandKVBASE should be VMALLOC_START. So fix it.
--- arch/arm64.c | 3 ++- makedumpfile.h | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-)
arch/arm64.c +2 -1
@@ -199,7 +199,8 @@ get_machdep_info_arm64(void) { info->max_physmem_bits =PHYS_MASK_SHIFT ; info->section_size_bits =SECTIONS_SIZE_BITS ; - info->page_offset =KVBASE ; + info->page_offset =SYMBOL (_stext) + & (0xffffffffffffffffUL << (VA_BITS -1 )); info->vmalloc_start =0xffffffffffffffffUL <<VA_BITS ; info->vmalloc_end =PAGE_OFFSET -PUD_SIZE -VMEMMAP_SIZE -0x10000 ; info->vmemmap_start =VMALLOC_END +0x10000 ;
makedumpfile.h +1 -2
@@ -507,8 +507,7 @@ int get_va_bits_arm64(void);#define ARM64_PGTABLE_LEVELS get_pgtable_level_arm64()#define VA_BITS get_va_bits_arm64()#define PAGE_SHIFT get_page_shift_arm64() -#define KVBASE_MASK (0xffffffffffffffffUL << (VA_BITS - 1)) -#define KVBASE (SYMBOL(_stext) & KVBASE_MASK) +#define KVBASE VMALLOC_START#endif /* aarch64 */ #ifdef __arm__
Signature · 7 lines
2.5.0 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH 2/4 arm64: Decide VA Bits on the basis of _stext symbol value
In reply to Pratyush AnandCurrently we assume that there are only two possible configuration supported by kernel.
1) Page Table Level:2, Page Size 64K and VA Bits 42
1) Page Table Level:3, Page Size 4K and VA Bits 39
Ideally, we should have some mechanism to decide these from kernel symbols, but we have limited symbols in vmcore, and we can not do much. So until some one comes with a better way, we use _stext symbol value for VA bits determination.
We also assume that when VA Bits are 39, Page table level will be 3 and Page size will be 4K, while when VA Bits are 42, Page table level will be 2 an Page size will be 64K.
--- arch/arm64.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-)
arch/arm64.c +27 -7
@@ -115,16 +115,36 @@ get_page_shift_arm64(void)return page_shift; } +#define PAGE_OFFSET_39 (0xffffffffffffffffUL << 39) +#define PAGE_OFFSET_42 (0xffffffffffffffffUL << 42)static int calculate_plat_config (void ) { -/* -* TODO: Keep it fixed for page level 2, size 64K and VA bits as -* 42, as of now. Will calculate them from symbol address values -* latter. +unsigned long long stext; + +/* Currently we assume that there are only two possible +* configuration supported by kernel. +* 1) Page Table Level:2, Page Size 64K and VA Bits 42 +* 1) Page Table Level:3, Page Size 4K and VA Bits 39 +* Ideally, we should have some mechanism to decide these values +* from kernel symbols, but we have limited symbols in vmcore, +* and we can not do much. So until some one comes with a better +* way, we use following. */ - pgtable_level =2 ; - va_bits =42 ; - page_shift =16 ; + stext =SYMBOL (_stext); + +/* condition for minimum VA bits must be checked first and so on */ +if ((stext &PAGE_OFFSET_39 ) ==PAGE_OFFSET_39 ) { + pgtable_level =3 ; + va_bits =39 ; + page_shift =12 ; + }else if ((stext &PAGE_OFFSET_42 ) ==PAGE_OFFSET_42 ) { + pgtable_level =2 ; + va_bits =42 ; + page_shift =16 ; + }else { +ERRMSG ("Kernel Configuration not supported\n" ); +return FALSE; + }return TRUE; }
Signature · 7 lines
2.5.0 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH 4/4 arm64: Fix for ARM64 3 level translation tables
In reply to Pratyush AnandFrom: Sameer Goel <[email protected]>
Add the implementation for PMD translation in case of 3 level page tables. Assign the kernel page size based on the page structure read from the kernel ELF file.
--- arch/arm64.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-)
arch/arm64.c +30 -6
@@ -36,7 +36,7 @@ typedef struct { } pmd_t;#define pud_offset (pgd, vaddr) ((pud_t *)pgd) -#define pmd_offset (pud, vaddr) ((pmd_t *)pud) +#define pgd_val (x) ((x).pgd)#define pud_val (x) (pgd_val((x).pgd))#define pmd_val (x) (pud_val((x).pud))
@@ -68,6 +68,11 @@ typedef struct {*/ #define PHYS_MASK_SHIFT 48#define PHYS_MASK ((1UL << PHYS_MASK_SHIFT) - 1) +/* +* Remove the highest order bits that are not a part of the +* physical address in a section +*/ +#define PMD_SECTION_MASK ((1UL << 40) - 1)#define PMD_TYPE_MASK 3#define PMD_TYPE_SECT 1
@@ -83,10 +88,18 @@ typedef struct {#define pmd_page_vaddr (pmd) (__va(pmd_val(pmd) & PHYS_MASK & (int32_t)PAGE_MASK))#define pte_offset (dir, vaddr) ((pte_t*)pmd_page_vaddr((*dir)) + pte_index(vaddr)) + +#define pmd_offset_pgtbl_lvl_2 (pud, vaddr) ((pmd_t *)pud) + +#define pmd_index (vaddr) (((vaddr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) +#define pud_page_vaddr (pud) (__va(pud_val(pud) & PHYS_MASK & (int32_t)PAGE_MASK)) +#define pmd_offset_pgtbl_lvl_3 (pud, vaddr) ((pmd_t *)pud_page_vaddr((*pud)) + pmd_index(vaddr)) +/* kernel struct page size can be kernel version dependent, currently * keep it constant. */ -#define KERN_STRUCT_PAGE_SIZE 64 +#define KERN_STRUCT_PAGE_SIZE get_structure_size("page", DWARF_INFO_GET_STRUCT_SIZE) +#define ALIGN (x, a) (((x) + (a) - 1) & ~((a) - 1))#define PFN_DOWN (x) ((x) >> PAGE_SHIFT)#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * KERN_STRUCT_PAGE_SIZE, PUD_SIZE)
@@ -97,6 +110,15 @@ static int pgtable_level;static int va_bits;static int page_shift; +pmd_t * +pmd_offset (pud_t *pud,unsigned long vaddr) +{ +if (pgtable_level ==2 ) { +return pmd_offset_pgtbl_lvl_2 (pud, vaddr); + }else { +return pmd_offset_pgtbl_lvl_3 (pud, vaddr); + } +}int get_pgtable_level_arm64 (void ) {
@@ -256,7 +278,7 @@ vtop_arm64(unsigned long vaddr) {unsigned long long paddr =NOT_PADDR ;pgd_t *pgda, pgdv; -pud_t *puda; +pud_t *puda, pudv;pmd_t *pmda, pmdv;pte_t *ptea, ptev;
@@ -271,8 +293,9 @@ vtop_arm64(unsigned long vaddr)return NOT_PADDR ; } - puda =pud_offset (pgda, vaddr); - pmda =pmd_offset (puda, vaddr); + pudv.pgd = pgdv; + + pmda =pmd_offset (&pudv, vaddr);if (!readmem (VADDR , (unsigned long long )pmda, &pmdv,sizeof (pmdv))) {ERRMSG ("Can't read pmd\n" );return NOT_PADDR ;
@@ -298,7 +321,8 @@ vtop_arm64(unsigned long vaddr)break ;case PMD_TYPE_SECT :/* 1GB section */ - paddr = (pmd_val (pmdv) &PMD_MASK ) + (vaddr & (PMD_SIZE -1 )); + paddr = (pmd_val (pmdv) & (PMD_MASK &PMD_SECTION_MASK )) + + (vaddr & (PMD_SIZE -1 ));break ; }
Signature · 7 lines
2.5.0 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 3/4] arm64: Fix KVBASE
In reply to Pratyush Anandarch/arm64.c get_machdep_info_arm64(void) · line 203
Quoted 1 line · Pratyush Anand
arch/arm64.c +1
-0+ & (0xffffffffffffffffUL << (VA_BITS -1 ));
Shouldn't this be ULL instead of just UL?
Signature · 8 lines
Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation. _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 3/4] arm64: Fix KVBASE
Hi Timur,
Thanks for your review.
Quoted 4 lines · Timur Tabi
arch/arm64.c get_machdep_info_arm64(void) · line 203
Quoted 1 line · Pratyush Anand
arch/arm64.c +1
-0+ & (0xffffffffffffffffUL << (VA_BITS -1 ));Shouldn't this be ULL instead of just UL?
I think on 64 bit platform, unsigned long is always 64 bit (with gcc). More over, info->page_offset is unsigned long. So, I think using UL would be in sync, no?
~Pratyush
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Hello Pratyush,
Quoted 6 lines
Hi Atsushi,
ARM64 was supporting only two level page support. These patches add support for 3 level page table as well.
~Pratyush
Thanks for your work, I'll merge these patches into v1.6.0.
Regards,
Atsushi Kumagai
Quoted 12 lines
Pratyush Anand (3):
ARM64: Refactor code to support multiple page level
arm64: Decide VA Bits on the basis of_stextsymbol value
arm64: Fix KVBASESameer Goel (1):
arm64: Fix for ARM64 3 level translation tables
arch/arm64.c| 103 +++++++++++++++++++++++++++++++++++++++++++++++++++------makedumpfile.h| 29 +++-------------2 files changed, 98 insertions(+), 34 deletions(-)
Quoted 8 lines
--
2.5.0_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec