Re: [PATCH v2 5/8] riscv: Implement sv48 support
Hi Nick, Le 6/27/20 à 8:30 AM, Nick Kossifidis a écrit : Στις 2020-06-03 11:11, Alexandre Ghiti έγραψε: By adding a new 4th level of page table, give the possibility to 64bit kernel to address 2^48 bytes of virtual address: in practice, that roughly offers ~160TB of virtual address space to userspace and allows up to 64TB of physical memory. If the underlying hardware does not support sv48, we will automatically fallback to a standard 3-level page table by folding the new PUD level into PGDIR level. In order to detect HW capabilities at runtime, we use SATP feature that ignores writes with an unsupported mode. Signed-off-by: Alexandre Ghiti Reviewed-by: Anup Patel --- arch/riscv/Kconfig | 6 +- arch/riscv/include/asm/csr.h | 3 +- arch/riscv/include/asm/fixmap.h | 1 + arch/riscv/include/asm/page.h | 15 +++ arch/riscv/include/asm/pgalloc.h | 36 +++ arch/riscv/include/asm/pgtable-64.h | 97 - arch/riscv/include/asm/pgtable.h | 10 +- arch/riscv/kernel/head.S | 3 +- arch/riscv/mm/context.c | 2 +- arch/riscv/mm/init.c | 158 +--- 10 files changed, 307 insertions(+), 24 deletions(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index e167f16131f4..3f73f60e9732 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -68,6 +68,7 @@ config RISCV select ARCH_HAS_GCOV_PROFILE_ALL select HAVE_COPY_THREAD_TLS select HAVE_ARCH_KASAN if MMU && 64BIT + select RELOCATABLE if 64BIT config ARCH_MMAP_RND_BITS_MIN default 18 if 64BIT @@ -106,7 +107,7 @@ config PAGE_OFFSET default 0xC000 if 32BIT && MAXPHYSMEM_2GB default 0x8000 if 64BIT && !MMU default 0x8000 if 64BIT && MAXPHYSMEM_2GB - default 0xffe0 if 64BIT && !MAXPHYSMEM_2GB + default 0xc000 if 64BIT && !MAXPHYSMEM_2GB config ARCH_FLATMEM_ENABLE def_bool y @@ -155,8 +156,11 @@ config GENERIC_HWEIGHT config FIX_EARLYCON_MEM def_bool MMU +# On a 64BIT relocatable kernel, the 4-level page table is at runtime folded +# on a 3-level page table when sv48 is not supported. config PGTABLE_LEVELS int + default 4 if 64BIT && RELOCATABLE default 3 if 64BIT default 2 diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index cec462e198ce..d41536c3f8d4 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -40,11 +40,10 @@ #ifndef CONFIG_64BIT #define SATP_PPN _AC(0x003F, UL) #define SATP_MODE_32 _AC(0x8000, UL) -#define SATP_MODE SATP_MODE_32 #else #define SATP_PPN _AC(0x0FFF, UL) #define SATP_MODE_39 _AC(0x8000, UL) -#define SATP_MODE SATP_MODE_39 +#define SATP_MODE_48 _AC(0x9000, UL) #endif /* Exception cause high bit - is an interrupt if set */ diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h index 2368d49eb4ef..d891cf9c73c5 100644 --- a/arch/riscv/include/asm/fixmap.h +++ b/arch/riscv/include/asm/fixmap.h @@ -27,6 +27,7 @@ enum fixed_addresses { FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1, FIX_PTE, FIX_PMD, + FIX_PUD, FIX_TEXT_POKE1, FIX_TEXT_POKE0, FIX_EARLYCON_MEM_BASE, diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h index 48bb09b6a9b7..5e77fe7f0d6d 100644 --- a/arch/riscv/include/asm/page.h +++ b/arch/riscv/include/asm/page.h @@ -31,7 +31,19 @@ * When not using MMU this corresponds to the first free page in * physical memory (aligned on a page boundary). */ +#ifdef CONFIG_RELOCATABLE +#define PAGE_OFFSET __page_offset + +#ifdef CONFIG_64BIT +/* + * By default, CONFIG_PAGE_OFFSET value corresponds to SV48 address space so + * define the PAGE_OFFSET value for SV39. + */ +#define PAGE_OFFSET_L3 0xffe0 +#endif /* CONFIG_64BIT */ +#else #define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) +#endif /* CONFIG_RELOCATABLE */ #define KERN_VIRT_SIZE (-PAGE_OFFSET) @@ -102,6 +114,9 @@ extern unsigned long pfn_base; extern unsigned long max_low_pfn; extern unsigned long min_low_pfn; extern unsigned long kernel_virt_addr; +#ifdef CONFIG_RELOCATABLE +extern unsigned long __page_offset; +#endif #define __pa_to_va_nodebug(x) ((void *)((unsigned long) (x) + va_pa_offset)) #define linear_mapping_va_to_pa(x) ((unsigned long)(x) - va_pa_offset) diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h index 3f601ee8233f..540eaa5a8658 100644 --- a/arch/riscv/include/asm/pgalloc.h +++ b/arch/riscv/include/asm/pgalloc.h @@ -36,6 +36,42 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) set_pud(pud, __pud((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE)); } + +static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud) +{ + if (pgtable_l4_enabled) { + unsigned
Re: [PATCH v2 5/8] riscv: Implement sv48 support
Στις 2020-06-03 11:11, Alexandre Ghiti έγραψε: By adding a new 4th level of page table, give the possibility to 64bit kernel to address 2^48 bytes of virtual address: in practice, that roughly offers ~160TB of virtual address space to userspace and allows up to 64TB of physical memory. If the underlying hardware does not support sv48, we will automatically fallback to a standard 3-level page table by folding the new PUD level into PGDIR level. In order to detect HW capabilities at runtime, we use SATP feature that ignores writes with an unsupported mode. Signed-off-by: Alexandre Ghiti Reviewed-by: Anup Patel --- arch/riscv/Kconfig | 6 +- arch/riscv/include/asm/csr.h| 3 +- arch/riscv/include/asm/fixmap.h | 1 + arch/riscv/include/asm/page.h | 15 +++ arch/riscv/include/asm/pgalloc.h| 36 +++ arch/riscv/include/asm/pgtable-64.h | 97 - arch/riscv/include/asm/pgtable.h| 10 +- arch/riscv/kernel/head.S| 3 +- arch/riscv/mm/context.c | 2 +- arch/riscv/mm/init.c| 158 +--- 10 files changed, 307 insertions(+), 24 deletions(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index e167f16131f4..3f73f60e9732 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -68,6 +68,7 @@ config RISCV select ARCH_HAS_GCOV_PROFILE_ALL select HAVE_COPY_THREAD_TLS select HAVE_ARCH_KASAN if MMU && 64BIT + select RELOCATABLE if 64BIT config ARCH_MMAP_RND_BITS_MIN default 18 if 64BIT @@ -106,7 +107,7 @@ config PAGE_OFFSET default 0xC000 if 32BIT && MAXPHYSMEM_2GB default 0x8000 if 64BIT && !MMU default 0x8000 if 64BIT && MAXPHYSMEM_2GB - default 0xffe0 if 64BIT && !MAXPHYSMEM_2GB + default 0xc000 if 64BIT && !MAXPHYSMEM_2GB config ARCH_FLATMEM_ENABLE def_bool y @@ -155,8 +156,11 @@ config GENERIC_HWEIGHT config FIX_EARLYCON_MEM def_bool MMU +# On a 64BIT relocatable kernel, the 4-level page table is at runtime folded +# on a 3-level page table when sv48 is not supported. config PGTABLE_LEVELS int + default 4 if 64BIT && RELOCATABLE default 3 if 64BIT default 2 diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index cec462e198ce..d41536c3f8d4 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -40,11 +40,10 @@ #ifndef CONFIG_64BIT #define SATP_PPN _AC(0x003F, UL) #define SATP_MODE_32 _AC(0x8000, UL) -#define SATP_MODE SATP_MODE_32 #else #define SATP_PPN _AC(0x0FFF, UL) #define SATP_MODE_39 _AC(0x8000, UL) -#define SATP_MODE SATP_MODE_39 +#define SATP_MODE_48 _AC(0x9000, UL) #endif /* Exception cause high bit - is an interrupt if set */ diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h index 2368d49eb4ef..d891cf9c73c5 100644 --- a/arch/riscv/include/asm/fixmap.h +++ b/arch/riscv/include/asm/fixmap.h @@ -27,6 +27,7 @@ enum fixed_addresses { FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1, FIX_PTE, FIX_PMD, + FIX_PUD, FIX_TEXT_POKE1, FIX_TEXT_POKE0, FIX_EARLYCON_MEM_BASE, diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h index 48bb09b6a9b7..5e77fe7f0d6d 100644 --- a/arch/riscv/include/asm/page.h +++ b/arch/riscv/include/asm/page.h @@ -31,7 +31,19 @@ * When not using MMU this corresponds to the first free page in * physical memory (aligned on a page boundary). */ +#ifdef CONFIG_RELOCATABLE +#define PAGE_OFFSET__page_offset + +#ifdef CONFIG_64BIT +/* + * By default, CONFIG_PAGE_OFFSET value corresponds to SV48 address space so + * define the PAGE_OFFSET value for SV39. + */ +#define PAGE_OFFSET_L3 0xffe0 +#endif /* CONFIG_64BIT */ +#else #define PAGE_OFFSET_AC(CONFIG_PAGE_OFFSET, UL) +#endif /* CONFIG_RELOCATABLE */ #define KERN_VIRT_SIZE (-PAGE_OFFSET) @@ -102,6 +114,9 @@ extern unsigned long pfn_base; extern unsigned long max_low_pfn; extern unsigned long min_low_pfn; extern unsigned long kernel_virt_addr; +#ifdef CONFIG_RELOCATABLE +extern unsigned long __page_offset; +#endif #define __pa_to_va_nodebug(x) ((void *)((unsigned long) (x) + va_pa_offset)) #define linear_mapping_va_to_pa(x) ((unsigned long)(x) - va_pa_offset) diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h index 3f601ee8233f..540eaa5a8658 100644 --- a/arch/riscv/include/asm/pgalloc.h +++ b/arch/riscv/include/asm/pgalloc.h @@ -36,6 +36,42 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) set_pud(pud, __pud((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE)); } + +static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud) +{ + if