@@ -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 */
@@ -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)
@@ -374,8 +374,20 @@ static void __init create_pte_mapping(pte_t *ptep,
{
uintptr_t pte_idx = pte_index(va);
- BUG_ON(sz != PAGE_SIZE);
+#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))