summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/Kconfig9
-rw-r--r--libcpu/risc-v/t-head/c906/mmu.c68
-rw-r--r--libcpu/risc-v/t-head/c906/riscv_mmu.h4
-rw-r--r--libcpu/risc-v/virt64/mmu.c67
-rw-r--r--libcpu/risc-v/virt64/startup_gcc.S38
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