Skip to content

Commit 0c34e79

Browse files
RISC-V: Introduce sv48 support without relocatable kernel
This patchset allows to have a single kernel for sv39 and sv48 without being relocatable. The idea comes from Arnd Bergmann who suggested to do the same as x86, that is mapping the kernel to the end of the address space, which allows the kernel to be linked at the same address for both sv39 and sv48 and then does not require to be relocated at runtime. This implements sv48 support at runtime. The kernel will try to boot with 4-level page table and will fallback to 3-level if the HW does not support it. Folding the 4th level into a 3-level page table has almost no cost at runtime. Note that kasan region had to be moved to the end of the address space since its location must be known at compile-time and then be valid for both sv39 and sv48 (and sv57 that is coming). * riscv-sv48-v3: riscv: Explicit comment about user virtual address space size riscv: Use pgtable_l4_enabled to output mmu_type in cpuinfo riscv: Implement sv48 support asm-generic: Prepare for riscv use of pud_alloc_one and pud_free riscv: Allow to dynamically define VA_BITS riscv: Introduce functions to switch pt_ops riscv: Split early kasan mapping to prepare sv48 introduction riscv: Move KASAN mapping next to the kernel mapping riscv: Get rid of MAXPHYSMEM configs Signed-off-by: Palmer Dabbelt <[email protected]>
2 parents fc839c6 + c774de2 commit 0c34e79

File tree

20 files changed

+731
-200
lines changed

20 files changed

+731
-200
lines changed

Documentation/riscv/vm-layout.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ RISC-V Linux Kernel SV39
4747
| Kernel-space virtual memory, shared between all processes:
4848
____________________________________________________________|___________________________________________________________
4949
| | | |
50-
ffffffc000000000 | -256 GB | ffffffc7ffffffff | 32 GB | kasan
51-
ffffffcefee00000 | -196 GB | ffffffcefeffffff | 2 MB | fixmap
52-
ffffffceff000000 | -196 GB | ffffffceffffffff | 16 MB | PCI io
53-
ffffffcf00000000 | -196 GB | ffffffcfffffffff | 4 GB | vmemmap
54-
ffffffd000000000 | -192 GB | ffffffdfffffffff | 64 GB | vmalloc/ioremap space
55-
ffffffe000000000 | -128 GB | ffffffff7fffffff | 124 GB | direct mapping of all physical memory
50+
ffffffc6fee00000 | -228 GB | ffffffc6feffffff | 2 MB | fixmap
51+
ffffffc6ff000000 | -228 GB | ffffffc6ffffffff | 16 MB | PCI io
52+
ffffffc700000000 | -228 GB | ffffffc7ffffffff | 4 GB | vmemmap
53+
ffffffc800000000 | -224 GB | ffffffd7ffffffff | 64 GB | vmalloc/ioremap space
54+
ffffffd800000000 | -160 GB | fffffff6ffffffff | 124 GB | direct mapping of all physical memory
55+
fffffff700000000 | -36 GB | fffffffeffffffff | 32 GB | kasan
5656
__________________|____________|__________________|_________|____________________________________________________________
5757
|
5858
|

arch/riscv/Kconfig

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -147,27 +147,16 @@ config MMU
147147
Select if you want MMU-based virtualised addressing space
148148
support by paged memory management. If unsure, say 'Y'.
149149

150-
config VA_BITS
151-
int
152-
default 32 if 32BIT
153-
default 39 if 64BIT
154-
155-
config PA_BITS
156-
int
157-
default 34 if 32BIT
158-
default 56 if 64BIT
159-
160150
config PAGE_OFFSET
161151
hex
162-
default 0xC0000000 if 32BIT && MAXPHYSMEM_1GB
152+
default 0xC0000000 if 32BIT
163153
default 0x80000000 if 64BIT && !MMU
164-
default 0xffffffff80000000 if 64BIT && MAXPHYSMEM_2GB
165-
default 0xffffffe000000000 if 64BIT && MAXPHYSMEM_128GB
154+
default 0xffffaf8000000000 if 64BIT
166155

167156
config KASAN_SHADOW_OFFSET
168157
hex
169158
depends on KASAN_GENERIC
170-
default 0xdfffffc800000000 if 64BIT
159+
default 0xdfffffff00000000 if 64BIT
171160
default 0xffffffff if 32BIT
172161

173162
config ARCH_FLATMEM_ENABLE
@@ -213,7 +202,7 @@ config FIX_EARLYCON_MEM
213202

214203
config PGTABLE_LEVELS
215204
int
216-
default 3 if 64BIT
205+
default 4 if 64BIT
217206
default 2
218207

219208
config LOCKDEP_SUPPORT
@@ -271,24 +260,6 @@ config MODULE_SECTIONS
271260
bool
272261
select HAVE_MOD_ARCH_SPECIFIC
273262

274-
choice
275-
prompt "Maximum Physical Memory"
276-
default MAXPHYSMEM_1GB if 32BIT
277-
default MAXPHYSMEM_2GB if 64BIT && CMODEL_MEDLOW
278-
default MAXPHYSMEM_128GB if 64BIT && CMODEL_MEDANY
279-
280-
config MAXPHYSMEM_1GB
281-
depends on 32BIT
282-
bool "1GiB"
283-
config MAXPHYSMEM_2GB
284-
depends on 64BIT
285-
bool "2GiB"
286-
config MAXPHYSMEM_128GB
287-
depends on 64BIT && CMODEL_MEDANY
288-
bool "128GiB"
289-
endchoice
290-
291-
292263
config SMP
293264
bool "Symmetric Multi-Processing"
294265
help

arch/riscv/configs/nommu_k210_defconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ CONFIG_EMBEDDED=y
2929
CONFIG_SLOB=y
3030
# CONFIG_MMU is not set
3131
CONFIG_SOC_CANAAN=y
32-
CONFIG_MAXPHYSMEM_2GB=y
3332
CONFIG_SMP=y
3433
CONFIG_NR_CPUS=2
3534
CONFIG_CMDLINE="earlycon console=ttySIF0"

arch/riscv/configs/nommu_k210_sdcard_defconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ CONFIG_EMBEDDED=y
2121
CONFIG_SLOB=y
2222
# CONFIG_MMU is not set
2323
CONFIG_SOC_CANAAN=y
24-
CONFIG_MAXPHYSMEM_2GB=y
2524
CONFIG_SMP=y
2625
CONFIG_NR_CPUS=2
2726
CONFIG_CMDLINE="earlycon console=ttySIF0 rootdelay=2 root=/dev/mmcblk0p1 ro"

arch/riscv/configs/nommu_virt_defconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ CONFIG_SLOB=y
2727
# CONFIG_SLAB_MERGE_DEFAULT is not set
2828
# CONFIG_MMU is not set
2929
CONFIG_SOC_VIRT=y
30-
CONFIG_MAXPHYSMEM_2GB=y
3130
CONFIG_SMP=y
3231
CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x10000000,115200n8 console=ttyS0"
3332
CONFIG_CMDLINE_FORCE=y

arch/riscv/include/asm/csr.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,13 @@
4040
#ifndef CONFIG_64BIT
4141
#define SATP_PPN _AC(0x003FFFFF, UL)
4242
#define SATP_MODE_32 _AC(0x80000000, UL)
43-
#define SATP_MODE SATP_MODE_32
4443
#define SATP_ASID_BITS 9
4544
#define SATP_ASID_SHIFT 22
4645
#define SATP_ASID_MASK _AC(0x1FF, UL)
4746
#else
4847
#define SATP_PPN _AC(0x00000FFFFFFFFFFF, UL)
4948
#define SATP_MODE_39 _AC(0x8000000000000000, UL)
50-
#define SATP_MODE SATP_MODE_39
49+
#define SATP_MODE_48 _AC(0x9000000000000000, UL)
5150
#define SATP_ASID_BITS 16
5251
#define SATP_ASID_SHIFT 44
5352
#define SATP_ASID_MASK _AC(0xFFFF, UL)

arch/riscv/include/asm/fixmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ enum fixed_addresses {
2424
FIX_HOLE,
2525
FIX_PTE,
2626
FIX_PMD,
27+
FIX_PUD,
2728
FIX_TEXT_POKE1,
2829
FIX_TEXT_POKE0,
2930
FIX_EARLYCON_MEM_BASE,

arch/riscv/include/asm/kasan.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,18 @@
2727
*/
2828
#define KASAN_SHADOW_SCALE_SHIFT 3
2929

30-
#define KASAN_SHADOW_SIZE (UL(1) << ((CONFIG_VA_BITS - 1) - KASAN_SHADOW_SCALE_SHIFT))
31-
#define KASAN_SHADOW_START KERN_VIRT_START
32-
#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
30+
#define KASAN_SHADOW_SIZE (UL(1) << ((VA_BITS - 1) - KASAN_SHADOW_SCALE_SHIFT))
31+
/*
32+
* Depending on the size of the virtual address space, the region may not be
33+
* aligned on PGDIR_SIZE, so force its alignment to ease its population.
34+
*/
35+
#define KASAN_SHADOW_START ((KASAN_SHADOW_END - KASAN_SHADOW_SIZE) & PGDIR_MASK)
36+
#define KASAN_SHADOW_END MODULES_LOWEST_VADDR
3337
#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
3438

3539
void kasan_init(void);
3640
asmlinkage void kasan_early_init(void);
41+
void kasan_swapper_init(void);
3742

3843
#endif
3944
#endif

arch/riscv/include/asm/page.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,20 @@
3131
* When not using MMU this corresponds to the first free page in
3232
* physical memory (aligned on a page boundary).
3333
*/
34+
#ifdef CONFIG_64BIT
35+
#ifdef CONFIG_MMU
36+
#define PAGE_OFFSET kernel_map.page_offset
37+
#else
3438
#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
35-
36-
#define KERN_VIRT_SIZE (-PAGE_OFFSET)
39+
#endif
40+
/*
41+
* By default, CONFIG_PAGE_OFFSET value corresponds to SV48 address space so
42+
* define the PAGE_OFFSET value for SV39.
43+
*/
44+
#define PAGE_OFFSET_L3 _AC(0xffffffd800000000, UL)
45+
#else
46+
#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
47+
#endif /* CONFIG_64BIT */
3748

3849
#ifndef __ASSEMBLY__
3950

@@ -86,6 +97,7 @@ extern unsigned long riscv_pfn_base;
8697
#endif /* CONFIG_MMU */
8798

8899
struct kernel_mapping {
100+
unsigned long page_offset;
89101
unsigned long virt_addr;
90102
uintptr_t phys_addr;
91103
uintptr_t size;

arch/riscv/include/asm/pgalloc.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <asm/tlb.h>
1212

1313
#ifdef CONFIG_MMU
14+
#define __HAVE_ARCH_PUD_ALLOC_ONE
15+
#define __HAVE_ARCH_PUD_FREE
1416
#include <asm-generic/pgalloc.h>
1517

1618
static inline void pmd_populate_kernel(struct mm_struct *mm,
@@ -36,6 +38,44 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
3638

3739
set_pud(pud, __pud((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
3840
}
41+
42+
static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
43+
{
44+
if (pgtable_l4_enabled) {
45+
unsigned long pfn = virt_to_pfn(pud);
46+
47+
set_p4d(p4d, __p4d((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
48+
}
49+
}
50+
51+
static inline void p4d_populate_safe(struct mm_struct *mm, p4d_t *p4d,
52+
pud_t *pud)
53+
{
54+
if (pgtable_l4_enabled) {
55+
unsigned long pfn = virt_to_pfn(pud);
56+
57+
set_p4d_safe(p4d,
58+
__p4d((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
59+
}
60+
}
61+
62+
#define pud_alloc_one pud_alloc_one
63+
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
64+
{
65+
if (pgtable_l4_enabled)
66+
return __pud_alloc_one(mm, addr);
67+
68+
return NULL;
69+
}
70+
71+
#define pud_free pud_free
72+
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
73+
{
74+
if (pgtable_l4_enabled)
75+
__pud_free(mm, pud);
76+
}
77+
78+
#define __pud_free_tlb(tlb, pud, addr) pud_free((tlb)->mm, pud)
3979
#endif /* __PAGETABLE_PMD_FOLDED */
4080

4181
static inline pgd_t *pgd_alloc(struct mm_struct *mm)

0 commit comments

Comments
 (0)