RISC-V: Implement late mapping page table allocation functions

Currently, page table setup is done during setup_va_final where fixmap can
be used to create the temporary mappings. The physical frame is allocated
from memblock_alloc_* functions. However, this won't work if page table
mapping needs to be created for a different mm context (i.e. efi mm) at
a later point of time.

Use generic kernel page allocation function & macros for any mapping
after setup_vm_final.

Signed-off-by: Atish Patra <atish.patra@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Acked-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>

authored by Atish Patra and committed by Palmer Dabbelt e8dcb61f 6262f661

+99 -31
+99 -31
arch/riscv/mm/init.c
··· 32 32 void *dtb_early_va __initdata; 33 33 uintptr_t dtb_early_pa __initdata; 34 34 35 + struct pt_alloc_ops { 36 + pte_t *(*get_pte_virt)(phys_addr_t pa); 37 + phys_addr_t (*alloc_pte)(uintptr_t va); 38 + #ifndef __PAGETABLE_PMD_FOLDED 39 + pmd_t *(*get_pmd_virt)(phys_addr_t pa); 40 + phys_addr_t (*alloc_pmd)(uintptr_t va); 41 + #endif 42 + }; 43 + 35 44 static void __init zone_sizes_init(void) 36 45 { 37 46 unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, }; ··· 212 203 } 213 204 214 205 #ifdef CONFIG_MMU 206 + static struct pt_alloc_ops pt_ops; 207 + 215 208 unsigned long va_pa_offset; 216 209 EXPORT_SYMBOL(va_pa_offset); 217 210 unsigned long pfn_base; ··· 222 211 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss; 223 212 pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss; 224 213 pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss; 225 - static bool mmu_enabled; 226 214 227 215 #define MAX_EARLY_MAPPING_SIZE SZ_128M 228 216 ··· 244 234 } 245 235 } 246 236 247 - static pte_t *__init get_pte_virt(phys_addr_t pa) 237 + static inline pte_t *__init get_pte_virt_early(phys_addr_t pa) 248 238 { 249 - if (mmu_enabled) { 250 - clear_fixmap(FIX_PTE); 251 - return (pte_t *)set_fixmap_offset(FIX_PTE, pa); 252 - } else { 253 - return (pte_t *)((uintptr_t)pa); 254 - } 239 + return (pte_t *)((uintptr_t)pa); 255 240 } 256 241 257 - static phys_addr_t __init alloc_pte(uintptr_t va) 242 + static inline pte_t *__init get_pte_virt_fixmap(phys_addr_t pa) 243 + { 244 + clear_fixmap(FIX_PTE); 245 + return (pte_t *)set_fixmap_offset(FIX_PTE, pa); 246 + } 247 + 248 + static inline pte_t *get_pte_virt_late(phys_addr_t pa) 249 + { 250 + return (pte_t *) __va(pa); 251 + } 252 + 253 + static inline phys_addr_t __init alloc_pte_early(uintptr_t va) 258 254 { 259 255 /* 260 256 * We only create PMD or PGD early mappings so we 261 257 * should never reach here with MMU disabled. 262 258 */ 263 - BUG_ON(!mmu_enabled); 259 + BUG(); 260 + } 264 261 262 + static inline phys_addr_t __init alloc_pte_fixmap(uintptr_t va) 263 + { 265 264 return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); 265 + } 266 + 267 + static phys_addr_t alloc_pte_late(uintptr_t va) 268 + { 269 + unsigned long vaddr; 270 + 271 + vaddr = __get_free_page(GFP_KERNEL); 272 + if (!vaddr || !pgtable_pte_page_ctor(virt_to_page(vaddr))) 273 + BUG(); 274 + return __pa(vaddr); 266 275 } 267 276 268 277 static void __init create_pte_mapping(pte_t *ptep, ··· 308 279 #endif 309 280 pmd_t early_pmd[PTRS_PER_PMD * NUM_EARLY_PMDS] __initdata __aligned(PAGE_SIZE); 310 281 311 - static pmd_t *__init get_pmd_virt(phys_addr_t pa) 282 + static pmd_t *__init get_pmd_virt_early(phys_addr_t pa) 312 283 { 313 - if (mmu_enabled) { 314 - clear_fixmap(FIX_PMD); 315 - return (pmd_t *)set_fixmap_offset(FIX_PMD, pa); 316 - } else { 317 - return (pmd_t *)((uintptr_t)pa); 318 - } 284 + /* Before MMU is enabled */ 285 + return (pmd_t *)((uintptr_t)pa); 319 286 } 320 287 321 - static phys_addr_t __init alloc_pmd(uintptr_t va) 288 + static pmd_t *__init get_pmd_virt_fixmap(phys_addr_t pa) 289 + { 290 + clear_fixmap(FIX_PMD); 291 + return (pmd_t *)set_fixmap_offset(FIX_PMD, pa); 292 + } 293 + 294 + static pmd_t *get_pmd_virt_late(phys_addr_t pa) 295 + { 296 + return (pmd_t *) __va(pa); 297 + } 298 + 299 + static phys_addr_t __init alloc_pmd_early(uintptr_t va) 322 300 { 323 301 uintptr_t pmd_num; 324 - 325 - if (mmu_enabled) 326 - return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); 327 302 328 303 pmd_num = (va - PAGE_OFFSET) >> PGDIR_SHIFT; 329 304 BUG_ON(pmd_num >= NUM_EARLY_PMDS); 330 305 return (uintptr_t)&early_pmd[pmd_num * PTRS_PER_PMD]; 306 + } 307 + 308 + static phys_addr_t __init alloc_pmd_fixmap(uintptr_t va) 309 + { 310 + return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); 311 + } 312 + 313 + static phys_addr_t alloc_pmd_late(uintptr_t va) 314 + { 315 + unsigned long vaddr; 316 + 317 + vaddr = __get_free_page(GFP_KERNEL); 318 + BUG_ON(!vaddr); 319 + return __pa(vaddr); 331 320 } 332 321 333 322 static void __init create_pmd_mapping(pmd_t *pmdp, ··· 363 316 } 364 317 365 318 if (pmd_none(pmdp[pmd_idx])) { 366 - pte_phys = alloc_pte(va); 319 + pte_phys = pt_ops.alloc_pte(va); 367 320 pmdp[pmd_idx] = pfn_pmd(PFN_DOWN(pte_phys), PAGE_TABLE); 368 - ptep = get_pte_virt(pte_phys); 321 + ptep = pt_ops.get_pte_virt(pte_phys); 369 322 memset(ptep, 0, PAGE_SIZE); 370 323 } else { 371 324 pte_phys = PFN_PHYS(_pmd_pfn(pmdp[pmd_idx])); 372 - ptep = get_pte_virt(pte_phys); 325 + ptep = pt_ops.get_pte_virt(pte_phys); 373 326 } 374 327 375 328 create_pte_mapping(ptep, va, pa, sz, prot); 376 329 } 377 330 378 331 #define pgd_next_t pmd_t 379 - #define alloc_pgd_next(__va) alloc_pmd(__va) 380 - #define get_pgd_next_virt(__pa) get_pmd_virt(__pa) 332 + #define alloc_pgd_next(__va) pt_ops.alloc_pmd(__va) 333 + #define get_pgd_next_virt(__pa) pt_ops.get_pmd_virt(__pa) 381 334 #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \ 382 335 create_pmd_mapping(__nextp, __va, __pa, __sz, __prot) 383 336 #define fixmap_pgd_next fixmap_pmd 384 337 #else 385 338 #define pgd_next_t pte_t 386 - #define alloc_pgd_next(__va) alloc_pte(__va) 387 - #define get_pgd_next_virt(__pa) get_pte_virt(__pa) 339 + #define alloc_pgd_next(__va) pt_ops.alloc_pte(__va) 340 + #define get_pgd_next_virt(__pa) pt_ops.get_pte_virt(__pa) 388 341 #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \ 389 342 create_pte_mapping(__nextp, __va, __pa, __sz, __prot) 390 343 #define fixmap_pgd_next fixmap_pte ··· 468 421 BUG_ON((load_pa % map_size) != 0); 469 422 BUG_ON(load_sz > MAX_EARLY_MAPPING_SIZE); 470 423 424 + pt_ops.alloc_pte = alloc_pte_early; 425 + pt_ops.get_pte_virt = get_pte_virt_early; 426 + #ifndef __PAGETABLE_PMD_FOLDED 427 + pt_ops.alloc_pmd = alloc_pmd_early; 428 + pt_ops.get_pmd_virt = get_pmd_virt_early; 429 + #endif 471 430 /* Setup early PGD for fixmap */ 472 431 create_pgd_mapping(early_pg_dir, FIXADDR_START, 473 432 (uintptr_t)fixmap_pgd_next, PGDIR_SIZE, PAGE_TABLE); ··· 550 497 phys_addr_t pa, start, end; 551 498 struct memblock_region *reg; 552 499 553 - /* Set mmu_enabled flag */ 554 - mmu_enabled = true; 555 - 500 + /** 501 + * MMU is enabled at this point. But page table setup is not complete yet. 502 + * fixmap page table alloc functions should be used at this point 503 + */ 504 + pt_ops.alloc_pte = alloc_pte_fixmap; 505 + pt_ops.get_pte_virt = get_pte_virt_fixmap; 506 + #ifndef __PAGETABLE_PMD_FOLDED 507 + pt_ops.alloc_pmd = alloc_pmd_fixmap; 508 + pt_ops.get_pmd_virt = get_pmd_virt_fixmap; 509 + #endif 556 510 /* Setup swapper PGD for fixmap */ 557 511 create_pgd_mapping(swapper_pg_dir, FIXADDR_START, 558 512 __pa_symbol(fixmap_pgd_next), ··· 593 533 /* Move to swapper page table */ 594 534 csr_write(CSR_SATP, PFN_DOWN(__pa_symbol(swapper_pg_dir)) | SATP_MODE); 595 535 local_flush_tlb_all(); 536 + 537 + /* generic page allocation functions must be used to setup page table */ 538 + pt_ops.alloc_pte = alloc_pte_late; 539 + pt_ops.get_pte_virt = get_pte_virt_late; 540 + #ifndef __PAGETABLE_PMD_FOLDED 541 + pt_ops.alloc_pmd = alloc_pmd_late; 542 + pt_ops.get_pmd_virt = get_pmd_virt_late; 543 + #endif 596 544 } 597 545 #else 598 546 asmlinkage void __init setup_vm(uintptr_t dtb_pa)