* @brief Early memory setup function for hardware initialization. * * This function performs early memory setup tasks, including: * - Calculating the physical-to-virtual (PV) offset. * - Setting up initial page tables for identity mapping and text region relocation. * - Applying new memory mappings by updating the SATP register. * * @note This function is typically called during the early s
| 663 | * Here the identity mapping is implemented by a 1-stage page table, whose page size is 1GB. |
| 664 | */ |
| 665 | void rt_hw_mem_setup_early(void) |
| 666 | { |
| 667 | rt_ubase_t pv_off; |
| 668 | rt_ubase_t ps = 0x0; |
| 669 | rt_ubase_t vs = 0x0; |
| 670 | rt_ubase_t *early_pgtbl = (rt_ubase_t *)(((size_t)&__bss_end + 4095) & ~0xfff); |
| 671 | |
| 672 | /* calculate pv_offset */ |
| 673 | void *symb_pc; |
| 674 | void *symb_linker; |
| 675 | __asm__ volatile("la %0, _start\n" : "=r"(symb_pc)); |
| 676 | __asm__ volatile("la %0, _start_link_addr\n" : "=r"(symb_linker)); |
| 677 | symb_linker = *(void **)symb_linker; |
| 678 | pv_off = symb_pc - symb_linker; |
| 679 | rt_kmem_pvoff_set(pv_off); |
| 680 | |
| 681 | if (pv_off) |
| 682 | { |
| 683 | if (pv_off & ((1ul << (ARCH_INDEX_WIDTH * 2 + ARCH_PAGE_SHIFT)) - 1)) |
| 684 | { |
| 685 | LOG_E("%s: not aligned virtual address. pv_offset %p", __func__, |
| 686 | pv_off); |
| 687 | RT_ASSERT(0); |
| 688 | } |
| 689 | |
| 690 | /** |
| 691 | * identical mapping, |
| 692 | * PC are still at lower region before relocating to high memory |
| 693 | */ |
| 694 | rt_ubase_t pg_idx ; |
| 695 | /* Round down symb_pc to L1_PAGE_SIZE boundary to ensure proper page alignment. |
| 696 | * This is necessary because MMU operations work with page-aligned addresses, and |
| 697 | * make sure all the text region is mapped.*/ |
| 698 | ps = (rt_ubase_t)symb_pc & (~(L1_PAGE_SIZE - 1)); |
| 699 | pg_idx = GET_L1(ps); |
| 700 | early_pgtbl[pg_idx] = COMBINEPTE(ps, MMU_MAP_EARLY); |
| 701 | |
| 702 | /* relocate text region */ |
| 703 | __asm__ volatile("la %0, _start\n" : "=r"(ps)); |
| 704 | ps &= ~(L1_PAGE_SIZE - 1); |
| 705 | vs = ps - pv_off; |
| 706 | |
| 707 | /* relocate region */ |
| 708 | rt_ubase_t vs_idx = GET_L1(vs); |
| 709 | rt_ubase_t ve_idx = GET_L1(vs + 0x80000000); |
| 710 | for (size_t i = vs_idx; i < ve_idx; i++) |
| 711 | { |
| 712 | early_pgtbl[i] = COMBINEPTE(ps, MMU_MAP_EARLY); |
| 713 | ps += L1_PAGE_SIZE; |
| 714 | } |
| 715 | |
| 716 | /* apply new mapping */ |
| 717 | asm volatile("sfence.vma x0, x0"); |
| 718 | write_csr(satp, SATP_BASE | ((size_t)early_pgtbl >> PAGE_OFFSET_BIT)); |
| 719 | asm volatile("sfence.vma x0, x0"); |
| 720 | } |
| 721 | /* return to lower text section */ |
| 722 | } |
nothing calls this directly
no test coverage detected