diff options
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/Kconfig | 9 | ||||
| -rw-r--r-- | libcpu/risc-v/t-head/c906/mmu.c | 68 | ||||
| -rw-r--r-- | libcpu/risc-v/t-head/c906/riscv_mmu.h | 4 | ||||
| -rw-r--r-- | libcpu/risc-v/virt64/mmu.c | 67 | ||||
| -rw-r--r-- | libcpu/risc-v/virt64/startup_gcc.S | 38 |
5 files changed, 178 insertions, 8 deletions
diff --git a/libcpu/Kconfig b/libcpu/Kconfig index 8c211de236..657fbfb0e9 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -133,6 +133,7 @@ if RT_USING_SMART hex "The virtural address of kernel start" default 0xffff000000000000 if ARCH_ARMV8 default 0xc0000000 if ARCH_ARM + default 0xffffffc000000000 if ARCH_RISCV && ARCH_REMAP_KERNEL default 0x80000000 if ARCH_RISCV depends on ARCH_MM_MMU @@ -255,6 +256,14 @@ config ARCH_RISCV64 select ARCH_CPU_64BIT bool +if ARCH_RISCV64 + config ARCH_REMAP_KERNEL + bool + depends on RT_USING_SMART + help + Remapping kernel image to high virtual address region +endif + config ARCH_IA32 bool diff --git a/libcpu/risc-v/t-head/c906/mmu.c b/libcpu/risc-v/t-head/c906/mmu.c index 39c2b59b5d..89f5e50106 100644 --- a/libcpu/risc-v/t-head/c906/mmu.c +++ b/libcpu/risc-v/t-head/c906/mmu.c @@ -18,6 +18,7 @@ #define DBG_LVL DBG_WARNING #include <rtdbg.h> +#include <board.h> #include <cache.h> #include <mm_aspace.h> #include <mm_page.h> @@ -324,6 +325,14 @@ static inline void _init_region(void *vaddr, size_t size) } #endif +#if defined(RT_USING_SMART) && defined(ARCH_REMAP_KERNEL) +#define KERN_SPACE_START ((void *)KERNEL_VADDR_START) +#define KERN_SPACE_SIZE (0xfffffffffffff000UL - KERNEL_VADDR_START + 0x1000) +#else +#define KERN_SPACE_START ((void *)0x1000) +#define KERN_SPACE_SIZE ((size_t)USER_VADDR_START - 0x1000) +#endif + int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_size_t size, rt_size_t *vtable, rt_size_t pv_off) { @@ -363,8 +372,7 @@ int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_size_t size, } } - rt_aspace_init(&rt_kernel_space, (void *)0x1000, USER_VADDR_START - 0x1000, - vtable); + rt_aspace_init(&rt_kernel_space, KERN_SPACE_START, KERN_SPACE_SIZE, vtable); _init_region(v_address, size); return 0; @@ -569,6 +577,62 @@ void rt_hw_mmu_kernel_map_init(rt_aspace_t aspace, rt_size_t vaddr_start, rt_siz rt_hw_tlb_invalidate_all_local(); } +#define SATP_BASE ((size_t)SATP_MODE << SATP_MODE_OFFSET) +void rt_hw_mem_setup_early(void) +{ + rt_size_t pv_off; + rt_size_t ps = 0x0; + rt_size_t vs = 0x0; + rt_size_t *early_pgtbl = (size_t *)(((size_t)&__bss_end + 4095) & ~0xfff); + + /* calculate pv_offset */ + void *symb_pc; + void *symb_linker; + __asm__ volatile("la %0, _start\n" : "=r"(symb_pc)); + __asm__ volatile("la %0, _start_link_addr\n" : "=r"(symb_linker)); + symb_linker = *(void **)symb_linker; + pv_off = symb_pc - symb_linker; + rt_kmem_pvoff_set(pv_off); + + if (pv_off) + { + if (pv_off & (1ul << (ARCH_INDEX_WIDTH * 2 + ARCH_PAGE_SHIFT))) + { + LOG_E("%s: not aligned virtual address. pv_offset %p", __func__, pv_off); + RT_ASSERT(0); + } + /** + * identical mapping, + * PC are still at lower region before relocating to high memory + */ + for (size_t i = 0; i < __SIZE(PPN0_BIT); i++) + { + early_pgtbl[i] = COMBINEPTE(ps, PAGE_ATTR_RWX | PTE_G | PTE_V); + ps += L1_PAGE_SIZE; + } + + /* relocate text region */ + __asm__ volatile("la %0, _start\n" : "=r"(ps)); + ps &= ~(L1_PAGE_SIZE - 1); + vs = ps - pv_off; + + /* relocate region */ + rt_size_t vs_idx = GET_L1(vs); + rt_size_t ve_idx = GET_L1(vs + 0x80000000); + for (size_t i = vs_idx; i < ve_idx; i++) + { + early_pgtbl[i] = COMBINEPTE(ps, PAGE_ATTR_RWX | PTE_G | PTE_V); + ps += L1_PAGE_SIZE; + } + + /* apply new mapping */ + asm volatile("sfence.vma x0, x0"); + write_csr(satp, SATP_BASE | ((size_t)early_pgtbl >> PAGE_OFFSET_BIT)); + asm volatile("sfence.vma x0, x0"); + } + /* return to lower text section */ +} + void *rt_hw_mmu_pgtbl_create(void) { size_t *mmu_table; diff --git a/libcpu/risc-v/t-head/c906/riscv_mmu.h b/libcpu/risc-v/t-head/c906/riscv_mmu.h index 983a86956c..6fc614eefb 100644 --- a/libcpu/risc-v/t-head/c906/riscv_mmu.h +++ b/libcpu/risc-v/t-head/c906/riscv_mmu.h @@ -64,8 +64,8 @@ #define PAGE_ATTR_CB (PTE_BUF | PTE_CACHE) #define PAGE_ATTR_DEV (PTE_SO) -#define PAGE_DEFAULT_ATTR_LEAF (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_U | PAGE_ATTR_RWX | PTE_V) -#define PAGE_DEFAULT_ATTR_NEXT (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_V) +#define PAGE_DEFAULT_ATTR_LEAF (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_G | PTE_U | PAGE_ATTR_RWX | PTE_V) +#define PAGE_DEFAULT_ATTR_NEXT (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_G | PTE_V) #define PAGE_IS_LEAF(pte) __MASKVALUE(pte, PAGE_ATTR_RWX) diff --git a/libcpu/risc-v/virt64/mmu.c b/libcpu/risc-v/virt64/mmu.c index c1a62bfdea..9d1bfd92e8 100644 --- a/libcpu/risc-v/virt64/mmu.c +++ b/libcpu/risc-v/virt64/mmu.c @@ -269,6 +269,14 @@ static inline void _init_region(void *vaddr, size_t size) } #endif +#if defined(RT_USING_SMART) && defined(ARCH_REMAP_KERNEL) +#define KERN_SPACE_START ((void *)KERNEL_VADDR_START) +#define KERN_SPACE_SIZE (0xfffffffffffff000UL - KERNEL_VADDR_START + 0x1000) +#else +#define KERN_SPACE_START ((void *)0x1000) +#define KERN_SPACE_SIZE ((size_t)USER_VADDR_START - 0x1000) +#endif + int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_size_t size, rt_size_t *vtable, rt_size_t pv_off) { @@ -308,8 +316,7 @@ int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_size_t size, } } - rt_aspace_init(&rt_kernel_space, (void *)0x1000, USER_VADDR_START - 0x1000, - vtable); + rt_aspace_init(&rt_kernel_space, KERN_SPACE_START, KERN_SPACE_SIZE, vtable); _init_region(v_address, size); return 0; @@ -492,6 +499,62 @@ void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr) rt_page_cleanup(); } +#define SATP_BASE ((size_t)SATP_MODE << SATP_MODE_OFFSET) +void rt_hw_mem_setup_early(void) +{ + rt_size_t pv_off; + rt_size_t ps = 0x0; + rt_size_t vs = 0x0; + rt_size_t *early_pgtbl = (size_t *)(((size_t)&__bss_end + 4095) & ~0xfff); + + /* calculate pv_offset */ + void *symb_pc; + void *symb_linker; + __asm__ volatile("la %0, _start\n" : "=r"(symb_pc)); + __asm__ volatile("la %0, _start_link_addr\n" : "=r"(symb_linker)); + symb_linker = *(void **)symb_linker; + pv_off = symb_pc - symb_linker; + rt_kmem_pvoff_set(pv_off); + + if (pv_off) + { + if (pv_off & (1ul << (ARCH_INDEX_WIDTH * 2 + ARCH_PAGE_SHIFT))) + { + LOG_E("%s: not aligned virtual address. pv_offset %p", __func__, pv_off); + RT_ASSERT(0); + } + /** + * identical mapping, + * PC are still at lower region before relocating to high memory + */ + for (size_t i = 0; i < __SIZE(PPN0_BIT); i++) + { + early_pgtbl[i] = COMBINEPTE(ps, PAGE_ATTR_RWX | PTE_G | PTE_V); + ps += L1_PAGE_SIZE; + } + + /* relocate text region */ + __asm__ volatile("la %0, _start\n" : "=r"(ps)); + ps &= ~(L1_PAGE_SIZE - 1); + vs = ps - pv_off; + + /* relocate region */ + rt_size_t vs_idx = GET_L1(vs); + rt_size_t ve_idx = GET_L1(vs + 0x80000000); + for (size_t i = vs_idx; i < ve_idx; i++) + { + early_pgtbl[i] = COMBINEPTE(ps, PAGE_ATTR_RWX | PTE_G | PTE_V); + ps += L1_PAGE_SIZE; + } + + /* apply new mapping */ + asm volatile("sfence.vma x0, x0"); + write_csr(satp, SATP_BASE | ((size_t)early_pgtbl >> PAGE_OFFSET_BIT)); + asm volatile("sfence.vma x0, x0"); + } + /* return to lower text section */ +} + void *rt_hw_mmu_pgtbl_create(void) { size_t *mmu_table; diff --git a/libcpu/risc-v/virt64/startup_gcc.S b/libcpu/risc-v/virt64/startup_gcc.S index d1d4ce11e5..cfa39f8535 100644 --- a/libcpu/risc-v/virt64/startup_gcc.S +++ b/libcpu/risc-v/virt64/startup_gcc.S @@ -94,5 +94,39 @@ _start: */ csrw sscratch, zero call init_bss - call sbi_init - j primary_cpu_entry +#ifdef ARCH_MM_MMU + call rt_hw_mem_setup_early + call rt_kmem_pvoff + /* a0 := pvoff */ + beq a0, zero, 1f + + /* relocate pc */ + la x1, _after_pc_relocation + sub x1, x1, a0 + ret +_after_pc_relocation: + /* relocate gp */ + sub gp, gp, a0 + + /* relocate context: sp */ + la sp, __stack_start__ + li t0, __STACKSIZE__ + add sp, sp, t0 + + /* reset s0-fp */ + mv s0, zero + + /* relocate stvec */ + la t0, trap_entry + csrw stvec, t0 +1: +#endif + call sbi_init + call primary_cpu_entry + +_never_return_here: + j . + +.global _start_link_addr +_start_link_addr: + .dword __text_start |
