Message ID | 20220822153413.4038052-3-panqinglin2020@iscas.ac.cn (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | riscv, mm: detect svnapot cpu support at runtime | expand |
Hey, Couple questions about some things that caught my eye. Mostly beyond my pay grade here though... On 22/08/2022 16:34, panqinglin2020@iscas.ac.cn wrote: > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe > > From: Qinglin Pan <panqinglin2020@iscas.ac.cn> > > Svnapot is powerful when a physical region is going to mapped to a > virtual region. Kernel will do like this when mapping all allocable > physical pages to kernel vm space. This commit modifies the > create_pte_mapping function used in linear-mapping procedure, so the > kernel can be able to use Svnapot when both address and length of > physical region are 64KB align. Code here will be executed only when > other size huge page is not suitable, so it can be an addition of > PMD_SIZE and PUD_SIZE mapping. > > This commit also modifies the best_map_size function to give map_size > many times instead of only once, so a memory region can be mapped by > both PMD_SIZE and 64KB napot size. > > It is tested by setting qemu's memory to a 262272k region, and the > kernel can boot successfully. > > Signed-off-by: Qinglin Pan <panqinglin2020@iscas.ac.cn> > > diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h > index cedcf8ea3c76..395fdc922e9e 100644 > --- a/arch/riscv/include/asm/mmu.h > +++ b/arch/riscv/include/asm/mmu.h > @@ -25,6 +25,7 @@ typedef struct { > > void __init create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa, > phys_addr_t sz, pgprot_t prot); > +void __init create_linear_mapping(void); > #endif /* __ASSEMBLY__ */ > > #endif /* _ASM_RISCV_MMU_H */ > diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c > index 95ef6e2bf45c..37e6f7044ef1 100644 > --- a/arch/riscv/kernel/setup.c > +++ b/arch/riscv/kernel/setup.c > @@ -292,13 +292,16 @@ void __init setup_arch(char **cmdline_p) > kasan_init(); > #endif > > -#ifdef CONFIG_SMP > - setup_smp(); > -#endif > - > riscv_fill_hwcap(); > riscv_init_cbom_blocksize(); > apply_boot_alternatives(); > + > + if (has_svnapot()) > + create_linear_mapping(); Does this now get called twice if has_svnapot()? Once here and once in paging_init(). > + > +#ifdef CONFIG_SMP > + setup_smp(); > +#endif Are there any side effects to moving this down? > } > > static int __init topology_init(void) > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index b56a0a75533f..f54c3991f9ab 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -373,9 +373,21 @@ static void __init create_pte_mapping(pte_t *ptep, > phys_addr_t sz, pgprot_t prot) > { > uintptr_t pte_idx = pte_index(va); > +#ifdef CONFIG_SVNAPOT > + pte_t pte; > + > + if (has_svnapot() && sz == NAPOT_CONT64KB_SIZE) { > + do { > + pte = pfn_pte(PFN_DOWN(pa), prot); > + ptep[pte_idx] = pte_mknapot(pte, NAPOT_CONT64KB_ORDER); > + pte_idx++; > + sz -= PAGE_SIZE; > + } while (sz > 0); > + return; > + } > +#endif > > BUG_ON(sz != PAGE_SIZE); > - > if (pte_none(ptep[pte_idx])) > ptep[pte_idx] = pfn_pte(PFN_DOWN(pa), prot); > } > @@ -673,10 +685,18 @@ void __init create_pgd_mapping(pgd_t *pgdp, > static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) > { > /* Upgrade to PMD_SIZE mappings whenever possible */ > - if ((base & (PMD_SIZE - 1)) || (size & (PMD_SIZE - 1))) > + base &= PMD_SIZE - 1; > + if (!base && size >= PMD_SIZE) > + return PMD_SIZE; > + > + if (!has_svnapot()) > return PAGE_SIZE; > > - return PMD_SIZE; > + base &= NAPOT_CONT64KB_SIZE - 1; > + if (!base && size >= NAPOT_CONT64KB_SIZE) > + return NAPOT_CONT64KB_SIZE; > + > + return PAGE_SIZE; > } > > #ifdef CONFIG_XIP_KERNEL > @@ -1090,18 +1110,12 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) > pt_ops_set_fixmap(); > } > > -static void __init setup_vm_final(void) > +void __init create_linear_mapping(void) > { > uintptr_t va, map_size; > phys_addr_t pa, start, end; > u64 i; > > - /* Setup swapper PGD for fixmap */ > - create_pgd_mapping(swapper_pg_dir, FIXADDR_START, > - __pa_symbol(fixmap_pgd_next), > - PGDIR_SIZE, PAGE_TABLE); > - > - /* Map all memory banks in the linear mapping */ > for_each_mem_range(i, &start, &end) { > if (start >= end) > break; > @@ -1111,14 +1125,25 @@ static void __init setup_vm_final(void) > if (end >= __pa(PAGE_OFFSET) + memory_limit) > end = __pa(PAGE_OFFSET) + memory_limit; > > - map_size = best_map_size(start, end - start); > for (pa = start; pa < end; pa += map_size) { > va = (uintptr_t)__va(pa); > + map_size = best_map_size(pa, end - pa); > > create_pgd_mapping(swapper_pg_dir, va, pa, map_size, > pgprot_from_va(va)); > } > } > +} > + > +static void __init setup_vm_final(void) > +{ > + /* Setup swapper PGD for fixmap */ > + create_pgd_mapping(swapper_pg_dir, FIXADDR_START, > + __pa_symbol(fixmap_pgd_next), > + PGDIR_SIZE, PAGE_TABLE); > + > + /* Map all memory banks in the linear mapping */ > + create_linear_mapping(); > > /* Map the kernel */ > if (IS_ENABLED(CONFIG_64BIT)) > -- > 2.35.1 > > > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv
diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h index cedcf8ea3c76..395fdc922e9e 100644 --- a/arch/riscv/include/asm/mmu.h +++ b/arch/riscv/include/asm/mmu.h @@ -25,6 +25,7 @@ typedef struct { void __init create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa, phys_addr_t sz, pgprot_t prot); +void __init create_linear_mapping(void); #endif /* __ASSEMBLY__ */ #endif /* _ASM_RISCV_MMU_H */ diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 95ef6e2bf45c..37e6f7044ef1 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -292,13 +292,16 @@ void __init setup_arch(char **cmdline_p) kasan_init(); #endif -#ifdef CONFIG_SMP - setup_smp(); -#endif - riscv_fill_hwcap(); riscv_init_cbom_blocksize(); apply_boot_alternatives(); + + if (has_svnapot()) + create_linear_mapping(); + +#ifdef CONFIG_SMP + setup_smp(); +#endif } static int __init topology_init(void) diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index b56a0a75533f..f54c3991f9ab 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -373,9 +373,21 @@ static void __init create_pte_mapping(pte_t *ptep, phys_addr_t sz, pgprot_t prot) { uintptr_t pte_idx = pte_index(va); +#ifdef CONFIG_SVNAPOT + pte_t pte; + + if (has_svnapot() && sz == NAPOT_CONT64KB_SIZE) { + do { + pte = pfn_pte(PFN_DOWN(pa), prot); + ptep[pte_idx] = pte_mknapot(pte, NAPOT_CONT64KB_ORDER); + pte_idx++; + sz -= PAGE_SIZE; + } while (sz > 0); + return; + } +#endif BUG_ON(sz != PAGE_SIZE); - if (pte_none(ptep[pte_idx])) ptep[pte_idx] = pfn_pte(PFN_DOWN(pa), prot); } @@ -673,10 +685,18 @@ void __init create_pgd_mapping(pgd_t *pgdp, static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) { /* Upgrade to PMD_SIZE mappings whenever possible */ - if ((base & (PMD_SIZE - 1)) || (size & (PMD_SIZE - 1))) + base &= PMD_SIZE - 1; + if (!base && size >= PMD_SIZE) + return PMD_SIZE; + + if (!has_svnapot()) return PAGE_SIZE; - return PMD_SIZE; + base &= NAPOT_CONT64KB_SIZE - 1; + if (!base && size >= NAPOT_CONT64KB_SIZE) + return NAPOT_CONT64KB_SIZE; + + return PAGE_SIZE; } #ifdef CONFIG_XIP_KERNEL @@ -1090,18 +1110,12 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) pt_ops_set_fixmap(); } -static void __init setup_vm_final(void) +void __init create_linear_mapping(void) { uintptr_t va, map_size; phys_addr_t pa, start, end; u64 i; - /* Setup swapper PGD for fixmap */ - create_pgd_mapping(swapper_pg_dir, FIXADDR_START, - __pa_symbol(fixmap_pgd_next), - PGDIR_SIZE, PAGE_TABLE); - - /* Map all memory banks in the linear mapping */ for_each_mem_range(i, &start, &end) { if (start >= end) break; @@ -1111,14 +1125,25 @@ static void __init setup_vm_final(void) if (end >= __pa(PAGE_OFFSET) + memory_limit) end = __pa(PAGE_OFFSET) + memory_limit; - map_size = best_map_size(start, end - start); for (pa = start; pa < end; pa += map_size) { va = (uintptr_t)__va(pa); + map_size = best_map_size(pa, end - pa); create_pgd_mapping(swapper_pg_dir, va, pa, map_size, pgprot_from_va(va)); } } +} + +static void __init setup_vm_final(void) +{ + /* Setup swapper PGD for fixmap */ + create_pgd_mapping(swapper_pg_dir, FIXADDR_START, + __pa_symbol(fixmap_pgd_next), + PGDIR_SIZE, PAGE_TABLE); + + /* Map all memory banks in the linear mapping */ + create_linear_mapping(); /* Map the kernel */ if (IS_ENABLED(CONFIG_64BIT))