mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-22 19:44:24 +08:00
[rt-smart] kernel virtual memory management layer (#6809)
synchronize virtual memory system works. adding kernel virtual memory management layer for page-based MMU enabled architecture porting libcpu MMU codes porting lwp memory related codes
This commit is contained in:
@@ -183,7 +183,7 @@ rt_hw_get_gtimer_frq:
|
||||
#ifdef RT_USING_LWP
|
||||
BL rt_thread_self
|
||||
MOV X19, X0
|
||||
BL lwp_mmu_switch
|
||||
BL lwp_aspace_switch
|
||||
MOV X0, X19
|
||||
BL lwp_user_setting_restore
|
||||
#endif
|
||||
@@ -514,28 +514,3 @@ vector_serror:
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
BL rt_hw_trap_serror
|
||||
b .
|
||||
|
||||
.global rt_hw_mmu_switch
|
||||
rt_hw_mmu_switch:
|
||||
MSR TTBR0_EL1, X0
|
||||
MRS X1, TCR_EL1
|
||||
CMP X0, XZR
|
||||
ORR X1, X1, #(1 << 7)
|
||||
BEQ 1f
|
||||
BIC X1, X1, #(1 << 7)
|
||||
1:
|
||||
MSR TCR_EL1, X1
|
||||
DSB SY
|
||||
ISB
|
||||
TLBI VMALLE1
|
||||
DSB SY
|
||||
ISB
|
||||
IC IALLUIS
|
||||
DSB SY
|
||||
ISB
|
||||
RET
|
||||
|
||||
.global rt_hw_mmu_tbl_get
|
||||
rt_hw_mmu_tbl_get:
|
||||
MRS X0, TTBR0_EL1
|
||||
RET
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
static inline rt_uint64_t get_secondary_entry_pa(void)
|
||||
{
|
||||
rt_uint64_t secondary_entry_pa = (rt_uint64_t)rt_hw_mmu_v2p(&mmu_info, _secondary_cpu_entry);
|
||||
rt_uint64_t secondary_entry_pa = (rt_uint64_t)rt_kmem_v2p(_secondary_cpu_entry);
|
||||
|
||||
if (!secondary_entry_pa)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define CPUPORT_H__
|
||||
|
||||
#include <armv8.h>
|
||||
#include <rtdef.h>
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
typedef union {
|
||||
@@ -29,12 +30,22 @@ rt_inline void rt_hw_isb(void)
|
||||
|
||||
rt_inline void rt_hw_dmb(void)
|
||||
{
|
||||
asm volatile ("dmb sy":::"memory");
|
||||
asm volatile ("dmb ish":::"memory");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_wmb(void)
|
||||
{
|
||||
asm volatile ("dmb ishst":::"memory");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_rmb(void)
|
||||
{
|
||||
asm volatile ("dmb ishld":::"memory");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_dsb(void)
|
||||
{
|
||||
asm volatile ("dsb sy":::"memory");
|
||||
asm volatile ("dsb ish":::"memory");
|
||||
}
|
||||
|
||||
#endif /*CPUPORT_H__*/
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
#include "gic.h"
|
||||
#include "gicv3.h"
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
#include "ioremap.h"
|
||||
#else
|
||||
#define rt_ioremap(x, ...) (x)
|
||||
#endif
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||||
|
||||
@@ -103,11 +109,11 @@ void rt_hw_interrupt_init(void)
|
||||
|
||||
/* initialize ARM GIC */
|
||||
#ifdef RT_USING_SMART
|
||||
gic_dist_base = (rt_uint64_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_dist_base(), 0x2000, MMU_MAP_K_DEVICE);
|
||||
gic_cpu_base = (rt_uint64_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_cpu_base(), 0x1000, MMU_MAP_K_DEVICE);
|
||||
gic_dist_base = (rt_uint64_t)rt_ioremap((void*)platform_get_gic_dist_base(), 0x2000);
|
||||
gic_cpu_base = (rt_uint64_t)rt_ioremap((void*)platform_get_gic_cpu_base(), 0x1000);
|
||||
#ifdef BSP_USING_GICV3
|
||||
gic_rdist_base = (rt_uint64_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_redist_base(),
|
||||
RT_CPUS_NR * (2 << 16), MMU_MAP_K_DEVICE);
|
||||
gic_rdist_base = (rt_uint64_t)rt_ioremap((void*)platform_get_gic_redist_base(),
|
||||
RT_CPUS_NR * (2 << 16));
|
||||
#endif
|
||||
#else
|
||||
gic_dist_base = platform_get_gic_dist_base();
|
||||
|
||||
+384
-734
File diff suppressed because it is too large
Load Diff
+52
-81
@@ -11,6 +11,7 @@
|
||||
#define __MMU_H_
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <mm_aspace.h>
|
||||
|
||||
/* normal memory wra mapping type */
|
||||
#define NORMAL_MEM 0
|
||||
@@ -25,6 +26,7 @@ struct mem_desc
|
||||
unsigned long vaddr_end;
|
||||
unsigned long paddr_start;
|
||||
unsigned long attr;
|
||||
struct rt_varea varea;
|
||||
};
|
||||
|
||||
#define MMU_AF_SHIFT 10
|
||||
@@ -37,60 +39,17 @@ struct mem_desc
|
||||
#define MMU_AP_KRUN 2UL /* kernel r, user none */
|
||||
#define MMU_AP_KRUR 3UL /* kernel r, user r */
|
||||
|
||||
#define MMU_MAP_K_RO (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
(MMU_AP_KRUN << MMU_AP_SHIFT) |\
|
||||
(NORMAL_MEM << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_K_RWCB (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
(MMU_AP_KAUN << MMU_AP_SHIFT) |\
|
||||
(NORMAL_MEM << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_K_RW (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
(MMU_AP_KAUN << MMU_AP_SHIFT) |\
|
||||
(NORMAL_NOCACHE_MEM << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_K_DEVICE (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
(MMU_AP_KAUN << MMU_AP_SHIFT) |\
|
||||
(DEVICE_MEM << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_U_RO (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
(MMU_AP_KRUR << MMU_AP_SHIFT) |\
|
||||
(NORMAL_NOCACHE_MEM << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_U_RWCB (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
(MMU_AP_KAUA << MMU_AP_SHIFT) |\
|
||||
(NORMAL_MEM << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_U_RW (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
(MMU_AP_KAUA << MMU_AP_SHIFT) |\
|
||||
(NORMAL_NOCACHE_MEM << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_U_DEVICE (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
(MMU_AP_KAUA << MMU_AP_SHIFT) |\
|
||||
(DEVICE_MEM << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_CUSTOM(ap, mtype) (\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
((ap) << MMU_AP_SHIFT) |\
|
||||
((mtype) << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_CUSTOM(ap, mtype) \
|
||||
((0x1UL << MMU_AF_SHIFT) | (0x2UL << MMU_SHARED_SHIFT) | \
|
||||
((ap) << MMU_AP_SHIFT) | ((mtype) << MMU_MA_SHIFT))
|
||||
#define MMU_MAP_K_RO MMU_MAP_CUSTOM(MMU_AP_KRUN, NORMAL_MEM)
|
||||
#define MMU_MAP_K_RWCB MMU_MAP_CUSTOM(MMU_AP_KAUN, NORMAL_MEM)
|
||||
#define MMU_MAP_K_RW MMU_MAP_CUSTOM(MMU_AP_KAUN, NORMAL_NOCACHE_MEM)
|
||||
#define MMU_MAP_K_DEVICE MMU_MAP_CUSTOM(MMU_AP_KAUN, DEVICE_MEM)
|
||||
#define MMU_MAP_U_RO MMU_MAP_CUSTOM(MMU_AP_KRUR, NORMAL_NOCACHE_MEM)
|
||||
#define MMU_MAP_U_RWCB MMU_MAP_CUSTOM(MMU_AP_KAUA, NORMAL_MEM)
|
||||
#define MMU_MAP_U_RW MMU_MAP_CUSTOM(MMU_AP_KAUA, NORMAL_NOCACHE_MEM)
|
||||
#define MMU_MAP_U_DEVICE MMU_MAP_CUSTOM(MMU_AP_KAUA, DEVICE_MEM)
|
||||
|
||||
#define ARCH_SECTION_SHIFT 21
|
||||
#define ARCH_SECTION_SIZE (1 << ARCH_SECTION_SHIFT)
|
||||
@@ -102,6 +61,7 @@ struct mem_desc
|
||||
#define ARCH_PAGE_TBL_SIZE (1 << ARCH_PAGE_TBL_SHIFT)
|
||||
#define ARCH_PAGE_TBL_MASK (ARCH_PAGE_TBL_SIZE - 1)
|
||||
|
||||
#define ARCH_VADDR_WIDTH 48
|
||||
#define ARCH_ADDRESS_WIDTH_BITS 64
|
||||
|
||||
#define MMU_MAP_ERROR_VANOTALIGN -1
|
||||
@@ -109,37 +69,48 @@ struct mem_desc
|
||||
#define MMU_MAP_ERROR_NOPAGE -3
|
||||
#define MMU_MAP_ERROR_CONFLICT -4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t *vtable;
|
||||
size_t vstart;
|
||||
size_t vend;
|
||||
size_t pv_off;
|
||||
} rt_mmu_info;
|
||||
#define ARCH_MAP_FAILED ((void *)0x1ffffffffffff)
|
||||
|
||||
void rt_hw_mmu_setup_early(unsigned long *tbl0, unsigned long *tbl1, unsigned long size, unsigned long pv_off);
|
||||
void rt_hw_mmu_setup(struct mem_desc *mdesc, int desc_nr);
|
||||
|
||||
int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void* v_address, size_t size, size_t *vtable, size_t pv_off);
|
||||
int rt_hw_mmu_ioremap_init(rt_mmu_info *mmu_info, void* v_address, size_t size);
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr);
|
||||
void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr);
|
||||
#else
|
||||
void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void* p_addr, size_t size, size_t attr);
|
||||
#endif
|
||||
|
||||
void rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size);
|
||||
void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr);
|
||||
struct rt_aspace;
|
||||
|
||||
void rt_hw_mmu_ktbl_set(unsigned long tbl);
|
||||
void *rt_hw_mmu_tbl_get();
|
||||
void rt_hw_mmu_switch(void *mmu_table);
|
||||
void rt_hw_mmu_setup_early(unsigned long *tbl0, unsigned long *tbl1,
|
||||
unsigned long size, unsigned long pv_off);
|
||||
void rt_hw_mmu_setup(struct rt_aspace *aspace, struct mem_desc *mdesc,
|
||||
int desc_nr);
|
||||
|
||||
void rt_hw_init_mmu_table(struct mem_desc *mdesc, rt_size_t desc_nr);
|
||||
void rt_hw_mmu_init(void);
|
||||
int rt_hw_mmu_map_init(struct rt_aspace *aspace, void *v_address,
|
||||
rt_size_t size, rt_size_t *vtable, rt_size_t pv_off);
|
||||
void *rt_hw_mmu_map(struct rt_aspace *aspace, void *v_addr, void *p_addr,
|
||||
size_t size, size_t attr);
|
||||
void rt_hw_mmu_unmap(struct rt_aspace *aspace, void *v_addr, size_t size);
|
||||
void rt_hw_aspace_switch(struct rt_aspace *aspace);
|
||||
void *rt_hw_mmu_v2p(struct rt_aspace *aspace, void *vaddr);
|
||||
void rt_hw_mmu_kernel_map_init(struct rt_aspace *aspace, rt_size_t vaddr_start,
|
||||
rt_size_t size);
|
||||
void rt_hw_mmu_ktbl_set(unsigned long tbl);
|
||||
|
||||
extern rt_mmu_info mmu_info;
|
||||
static inline void *rt_hw_mmu_tbl_get()
|
||||
{
|
||||
uintptr_t tbl;
|
||||
__asm__ volatile("MRS %0, TTBR0_EL1" : "=r"(tbl));
|
||||
return (void *)(tbl & ((1ul << 48) - 2));
|
||||
}
|
||||
|
||||
static inline void *_rt_kmem_v2p(void *vaddr)
|
||||
{
|
||||
return rt_hw_mmu_v2p(&rt_kernel_space, vaddr);
|
||||
}
|
||||
|
||||
static inline void *rt_kmem_v2p(void *vaddr)
|
||||
{
|
||||
MM_PGTBL_LOCK(&rt_kernel_space);
|
||||
void *paddr = _rt_kmem_v2p(vaddr);
|
||||
MM_PGTBL_UNLOCK(&rt_kernel_space);
|
||||
return paddr;
|
||||
}
|
||||
|
||||
int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size,
|
||||
enum rt_mmu_cntl cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-11-28 WangXiaoyao the first version
|
||||
*/
|
||||
#ifndef __TLB_H__
|
||||
#define __TLB_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "mm_aspace.h"
|
||||
#include "mmu.h"
|
||||
|
||||
#define TLBI_ARG(addr, asid) \
|
||||
({ \
|
||||
uintptr_t arg = (uintptr_t)(addr) >> 12; \
|
||||
arg &= (1ull << 44) - 1; \
|
||||
arg |= (uintptr_t)(asid) << 48; \
|
||||
(void *)arg; \
|
||||
})
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_all(void)
|
||||
{
|
||||
__asm__ volatile(
|
||||
// ensure updates to pte completed
|
||||
"dsb ishst\n"
|
||||
"tlbi vmalle1is\n"
|
||||
"dsb ish\n"
|
||||
// after tlb in new context, refresh inst
|
||||
"isb\n" ::
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_all_local(void)
|
||||
{
|
||||
__asm__ volatile(
|
||||
// ensure updates to pte completed
|
||||
"dsb nshst\n"
|
||||
"tlbi vmalle1is\n"
|
||||
"dsb nsh\n"
|
||||
// after tlb in new context, refresh inst
|
||||
"isb\n" ::
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_aspace(rt_aspace_t aspace)
|
||||
{
|
||||
rt_hw_tlb_invalidate_all_local();
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_page(rt_aspace_t aspace, void *start)
|
||||
{
|
||||
start = TLBI_ARG(start, 0);
|
||||
__asm__ volatile(
|
||||
"dsb ishst\n"
|
||||
"tlbi vaae1is, %0\n"
|
||||
"dsb ish\n"
|
||||
"isb\n" ::"r"(start)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_range(rt_aspace_t aspace, void *start,
|
||||
size_t size, size_t stride)
|
||||
{
|
||||
if (size < ARCH_PAGE_SIZE)
|
||||
{
|
||||
rt_hw_tlb_invalidate_page(aspace, start);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_tlb_invalidate_aspace(aspace);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __TLB_H__ */
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <armv8.h>
|
||||
#include "interrupt.h"
|
||||
#include "mm_fault.h"
|
||||
|
||||
#include <backtrace.h>
|
||||
|
||||
@@ -48,6 +49,29 @@ void check_user_fault(struct rt_hw_exp_stack *regs, uint32_t pc_adj, char *info)
|
||||
}
|
||||
}
|
||||
|
||||
int _get_type(unsigned long esr)
|
||||
{
|
||||
int ret;
|
||||
int fsc = esr & 0x3f;
|
||||
switch (fsc)
|
||||
{
|
||||
case 0x4:
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
case 0x7:
|
||||
ret = MM_FAULT_TYPE_PAGE_FAULT;
|
||||
break;
|
||||
case 0x9:
|
||||
case 0xa:
|
||||
case 0xb:
|
||||
ret = MM_FAULT_TYPE_ACCESS_FAULT;
|
||||
break;
|
||||
default:
|
||||
ret = MM_FAULT_TYPE_GENERIC;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int check_user_stack(unsigned long esr, struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
unsigned char ec;
|
||||
@@ -55,19 +79,36 @@ int check_user_stack(unsigned long esr, struct rt_hw_exp_stack *regs)
|
||||
int ret = 0;
|
||||
|
||||
ec = (unsigned char)((esr >> 26) & 0x3fU);
|
||||
enum rt_mm_fault_op fault_op;
|
||||
enum rt_mm_fault_type fault_type;
|
||||
switch (ec)
|
||||
{
|
||||
case 0x20:
|
||||
fault_op = MM_FAULT_OP_EXECUTE;
|
||||
fault_type = _get_type(esr);
|
||||
break;
|
||||
case 0x21:
|
||||
case 0x24:
|
||||
fault_op = MM_FAULT_OP_WRITE;
|
||||
fault_type = _get_type(esr);
|
||||
break;
|
||||
default:
|
||||
fault_op = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (fault_op)
|
||||
{
|
||||
asm volatile("mrs %0, far_el1":"=r"(dfar));
|
||||
if (arch_expand_user_stack(dfar))
|
||||
struct rt_mm_fault_msg msg = {
|
||||
.fault_op = fault_op,
|
||||
.fault_type = fault_type,
|
||||
.vaddr = dfar,
|
||||
};
|
||||
if (rt_mm_fault_try_fix(&msg))
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -91,10 +91,11 @@ __start:
|
||||
msr cpacr_el1, x1
|
||||
|
||||
/* clear bss */
|
||||
ldr x1, =__bss_start /* get bss start address */
|
||||
ldr x2, =__bss_end
|
||||
adrp x1, __bss_start /* get bss start address */
|
||||
add x1, x1, #:lo12:__bss_start
|
||||
adrp x2, __bss_end
|
||||
add x1, x1, #:lo12:__bss_end
|
||||
sub x2, x2, x1 /* get bss size */
|
||||
add x1, x1, x9
|
||||
|
||||
and x3, x2, #7 /* x3 is < 7 */
|
||||
ldr x4, =~0x7
|
||||
@@ -140,14 +141,14 @@ __start:
|
||||
orr x1, x1, #(1 << 0) /* M */
|
||||
msr sctlr_el1, x1 /* enable MMU */
|
||||
|
||||
dsb sy
|
||||
isb sy
|
||||
dsb ish
|
||||
isb
|
||||
ic ialluis /* Invalidate all instruction caches in Inner Shareable domain to Point of Unification */
|
||||
dsb sy
|
||||
isb sy
|
||||
dsb ish
|
||||
isb
|
||||
tlbi vmalle1 /* Invalidate all stage 1 translations used at EL1 with the current VMID */
|
||||
dsb sy
|
||||
isb sy
|
||||
dsb ish
|
||||
isb
|
||||
ret
|
||||
|
||||
after_mmu_enable:
|
||||
|
||||
@@ -53,7 +53,7 @@ rt_hw_context_switch_to:
|
||||
#ifdef RT_USING_SMART
|
||||
bl rt_thread_self
|
||||
mov r4, r0
|
||||
bl lwp_mmu_switch
|
||||
bl lwp_aspace_switch
|
||||
mov r0, r4
|
||||
bl lwp_user_setting_restore
|
||||
#endif
|
||||
@@ -116,7 +116,7 @@ rt_hw_context_switch:
|
||||
#ifdef RT_USING_SMART
|
||||
bl rt_thread_self
|
||||
mov r4, r0
|
||||
bl lwp_mmu_switch
|
||||
bl lwp_aspace_switch
|
||||
mov r0, r4
|
||||
bl lwp_user_setting_restore
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef CPUPORT_H__
|
||||
#define CPUPORT_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
/* the exception stack without VFP registers */
|
||||
struct rt_hw_exp_stack
|
||||
{
|
||||
|
||||
@@ -70,8 +70,8 @@ void rt_hw_interrupt_init(void)
|
||||
|
||||
/* initialize ARM GIC */
|
||||
#ifdef RT_USING_SMART
|
||||
gic_dist_base = (uint32_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_dist_base(), 0x2000, MMU_MAP_K_RW);
|
||||
gic_cpu_base = (uint32_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_cpu_base(), 0x1000, MMU_MAP_K_RW);
|
||||
gic_dist_base = (uint32_t)rt_ioremap((void*)platform_get_gic_dist_base(), 0x2000);
|
||||
gic_cpu_base = (uint32_t)rt_ioremap((void*)platform_get_gic_cpu_base(), 0x1000);
|
||||
#else
|
||||
gic_dist_base = platform_get_gic_dist_base();
|
||||
gic_cpu_base = platform_get_gic_cpu_base();
|
||||
@@ -100,7 +100,8 @@ void rt_hw_interrupt_init(void)
|
||||
|
||||
/* initialize ARM GIC */
|
||||
#ifdef RT_USING_SMART
|
||||
gic_dist_base = (uint32_t)rt_hw_mmu_map(&mmu_info, 0, (void*)platform_get_gic_dist_base(), 0x2000, MMU_MAP_K_RW);
|
||||
gic_dist_base = (uint32_t)rt_ioremap((void*)platform_get_gic_dist_base(), 0x2000);
|
||||
gic_cpu_base = (uint32_t)rt_ioremap((void*)platform_get_gic_cpu_base(), 0x1000);
|
||||
#else
|
||||
gic_dist_base = platform_get_gic_dist_base();
|
||||
#endif
|
||||
|
||||
+171
-578
File diff suppressed because it is too large
Load Diff
+34
-17
@@ -11,6 +11,7 @@
|
||||
#define __MMU_H_
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <mm_aspace.h>
|
||||
|
||||
#define DESC_SEC (0x2)
|
||||
#define MEMWBWA ((1<<12)|(3<<2)) /* write back, write allocate */
|
||||
@@ -87,27 +88,43 @@ struct mem_desc
|
||||
#define ARCH_TYPE_SUPERSECTION (1 << 18)
|
||||
|
||||
#define ARCH_ADDRESS_WIDTH_BITS 32
|
||||
#define ARCH_VADDR_WIDTH 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t *vtable;
|
||||
size_t vstart;
|
||||
size_t vend;
|
||||
size_t pv_off;
|
||||
} rt_mmu_info;
|
||||
/**
|
||||
* *info it's possible to map (-1ul & ~ARCH_PAGE_MASK) but a not aligned -1 is
|
||||
* never returned on a successful mapping
|
||||
*/
|
||||
#define ARCH_MAP_FAILED ((void *)-1)
|
||||
|
||||
int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void* v_address, size_t size, size_t *vtable, size_t pv_off);
|
||||
int rt_hw_mmu_ioremap_init(rt_mmu_info *mmu_info, void* v_address, size_t size);
|
||||
int rt_hw_mmu_ioremap_init(struct rt_aspace *aspace, void *v_address, size_t size);
|
||||
void rt_hw_init_mmu_table(struct mem_desc *mdesc, rt_uint32_t size);
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr);
|
||||
void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr);
|
||||
#else
|
||||
void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void* p_addr, size_t size, size_t attr);
|
||||
#endif
|
||||
void rt_hw_mmu_setup(struct rt_aspace *aspace, struct mem_desc *mdesc, int desc_nr);
|
||||
|
||||
void rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size);
|
||||
void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr);
|
||||
int rt_hw_mmu_map_init(struct rt_aspace *aspace, void *v_address, size_t size, size_t *vtable, size_t pv_off);
|
||||
void *rt_hw_mmu_map(struct rt_aspace *aspace, void *v_addr, void *p_addr, size_t size, size_t attr);
|
||||
void rt_hw_mmu_unmap(struct rt_aspace *aspace, void *v_addr, size_t size);
|
||||
|
||||
void rt_hw_aspace_switch(struct rt_aspace *aspace);
|
||||
void rt_hw_mmu_switch(void *tbl);
|
||||
|
||||
void *rt_hw_mmu_v2p(struct rt_aspace *aspace, void *vaddr);
|
||||
void rt_hw_mmu_kernel_map_init(struct rt_aspace *aspace, size_t vaddr_start, size_t size);
|
||||
void *rt_hw_mmu_tbl_get();
|
||||
|
||||
static inline void *_rt_kmem_v2p(void *vaddr)
|
||||
{
|
||||
return rt_hw_mmu_v2p(&rt_kernel_space, vaddr);
|
||||
}
|
||||
|
||||
static inline void *rt_kmem_v2p(void *vaddr)
|
||||
{
|
||||
MM_PGTBL_LOCK(&rt_kernel_space);
|
||||
void *paddr = _rt_kmem_v2p(vaddr);
|
||||
MM_PGTBL_UNLOCK(&rt_kernel_space);
|
||||
return paddr;
|
||||
}
|
||||
|
||||
int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size, enum rt_mmu_cntl cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -258,34 +258,27 @@ rt_hw_set_process_id:
|
||||
MCR p15, 0, r0, c13, c0, 1
|
||||
mov pc, lr
|
||||
|
||||
#endif
|
||||
.global rt_hw_mmu_switch
|
||||
rt_hw_mmu_switch:
|
||||
mov r3, #0
|
||||
mcr p15, 0, r3, c13, c0, 1 /* set contextid = 0, for synchronization*/
|
||||
isb
|
||||
|
||||
orr r0, #0x18
|
||||
mcr p15, 0, r0, c2, c0, 0 /* ttbr0 */
|
||||
mcr p15, 0, r0, c2, c0, 0 // ttbr0
|
||||
|
||||
isb
|
||||
mov r1, r1, LSL #0x8
|
||||
and r2, r2, #0xff
|
||||
orr r1, r1, r2 /* contextid.PROCID = pid, contextid.ASID = asid*/
|
||||
mcr p15, 0, r1, c13, c0, 1 /* set contextid = r1*/
|
||||
isb
|
||||
|
||||
mcr p15, 0, r0, c7, c5, 0 /* iciallu */
|
||||
mcr p15, 0, r0, c7, c5, 6 /* bpiall */
|
||||
//invalid tlb
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c8, c7, 0
|
||||
mcr p15, 0, r0, c7, c5, 0 //iciallu
|
||||
mcr p15, 0, r0, c7, c5, 6 //bpiall
|
||||
|
||||
dsb
|
||||
isb
|
||||
mov pc, lr
|
||||
|
||||
.global rt_hw_mmu_tbl_get
|
||||
rt_hw_mmu_tbl_get:
|
||||
mrc p15, 0, r0, c2, c0, 0 /* ttbr0 */
|
||||
bic r0, #0x18
|
||||
mov pc, lr
|
||||
#endif
|
||||
|
||||
_halt:
|
||||
wfe
|
||||
@@ -459,7 +452,7 @@ rt_hw_context_switch_interrupt_do:
|
||||
bl rt_thread_self
|
||||
#ifdef RT_USING_SMART
|
||||
mov r4, r0
|
||||
bl lwp_mmu_switch
|
||||
bl lwp_aspace_switch
|
||||
mov r0, r4
|
||||
bl lwp_user_setting_restore
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-12-12 WangXiaoyao the first version
|
||||
*/
|
||||
#ifndef __TLB_H__
|
||||
#define __TLB_H__
|
||||
|
||||
#include "mm_aspace.h"
|
||||
#include <rtthread.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define dsb(scope) __asm__ volatile("dsb " #scope : : : "memory")
|
||||
#define isb() __asm__ volatile("isb" : : : "memory")
|
||||
#define STORE_CP32(r, name...) "mcr " RT_STRINGIFY(CP32(%r, name)) ";"
|
||||
|
||||
#define WRITE_CP32(v, name...) do { \
|
||||
register uint32_t _r = (v); \
|
||||
asm volatile(STORE_CP32(0, name) : : "r" (_r)); \
|
||||
} while (0)
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_all(void)
|
||||
{
|
||||
asm volatile ("mcr p15, 0, r0, c8, c7, 0\ndsb\nisb" ::: "memory");
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_all_local(void)
|
||||
{
|
||||
rt_hw_tlb_invalidate_all();
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_aspace(rt_aspace_t aspace)
|
||||
{
|
||||
rt_hw_tlb_invalidate_all();
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_range(rt_aspace_t aspace, void *start,
|
||||
size_t size, size_t stride)
|
||||
{
|
||||
rt_hw_tlb_invalidate_all();
|
||||
}
|
||||
|
||||
#endif /* __TLB_H__ */
|
||||
@@ -8,12 +8,13 @@
|
||||
* 2013-07-20 Bernard first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <board.h>
|
||||
#include <backtrace.h>
|
||||
#include <board.h>
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "interrupt.h"
|
||||
#include "mm_fault.h"
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
extern long list_thread(void);
|
||||
@@ -44,14 +45,23 @@ void check_user_fault(struct rt_hw_exp_stack *regs, uint32_t pc_adj, char *info)
|
||||
|
||||
int check_user_stack(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
void* dfar = RT_NULL;
|
||||
void *dfar = RT_NULL;
|
||||
asm volatile("MRC p15, 0, %0, c6, c0, 0" : "=r"(dfar));
|
||||
|
||||
asm volatile ("MRC p15, 0, %0, c6, c0, 0":"=r"(dfar));
|
||||
if (arch_expand_user_stack(dfar))
|
||||
if ((dfar >= (void *)USER_STACK_VSTART) && (dfar < (void *)USER_STACK_VEND))
|
||||
{
|
||||
regs->pc -= 8;
|
||||
return 1;
|
||||
struct rt_mm_fault_msg msg = {
|
||||
.fault_op = MM_FAULT_OP_WRITE,
|
||||
.fault_type = MM_FAULT_TYPE_PAGE_FAULT,
|
||||
.vaddr = dfar,
|
||||
};
|
||||
if (rt_mm_fault_try_fix(&msg))
|
||||
{
|
||||
regs->pc -= 8;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -79,7 +89,7 @@ void rt_hw_show_register(struct rt_hw_exp_stack *regs)
|
||||
rt_kprintf("ttbr0:0x%08x\n", v);
|
||||
asm volatile ("MRC p15, 0, %0, c6, c0, 0":"=r"(v));
|
||||
rt_kprintf("dfar:0x%08x\n", v);
|
||||
rt_kprintf("0x%08x -> 0x%08x\n", v, rt_hw_mmu_v2p(&mmu_info, (void *)v));
|
||||
rt_kprintf("0x%08x -> 0x%08x\n", v, rt_kmem_v2p((void *)v));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#ifdef RT_USING_SMART
|
||||
#include <lwp_arch.h>
|
||||
|
||||
#define TRANCE_LEVEL 20
|
||||
|
||||
extern rt_ubase_t __text_start[];
|
||||
extern rt_ubase_t __text_end[];
|
||||
|
||||
static char *_get_elf_name(size_t sepc);
|
||||
|
||||
void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc)
|
||||
{
|
||||
rt_ubase_t *ra;
|
||||
rt_ubase_t *fp;
|
||||
rt_ubase_t vas, vae;
|
||||
int i, j;
|
||||
|
||||
rt_kprintf("riscv64-unknown-linux-musl-addr2line -e %s -a -f", _get_elf_name(sepc));
|
||||
|
||||
fp = (rt_ubase_t *)ffp;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
asm volatile("mv %0, s0"
|
||||
: "=r"(fp));
|
||||
}
|
||||
|
||||
if (sepc)
|
||||
{
|
||||
rt_kprintf(" %p", sepc - 0x4);
|
||||
}
|
||||
|
||||
if (fp > (rt_ubase_t *)USER_VADDR_START && fp < (rt_ubase_t *)USER_VADDR_TOP)
|
||||
{
|
||||
vas = USER_VADDR_START;
|
||||
vae = USER_VADDR_TOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
vas = (rt_ubase_t)&__text_start;
|
||||
vae = (rt_ubase_t)&__text_end;
|
||||
}
|
||||
|
||||
for (i = j = 0; i < TRANCE_LEVEL; i++)
|
||||
{
|
||||
if (RT_ALIGN((rt_ubase_t)fp, sizeof(void *)) != (rt_ubase_t)fp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ra = fp - 1;
|
||||
if (!_rt_kmem_v2p(ra) || *ra < vas || *ra > vae)
|
||||
break;
|
||||
|
||||
rt_kprintf(" %p", *ra - 0x04);
|
||||
|
||||
fp = fp - 2;
|
||||
if (!_rt_kmem_v2p(fp))
|
||||
break;
|
||||
fp = (rt_ubase_t *)(*fp);
|
||||
if (!fp)
|
||||
break;
|
||||
}
|
||||
|
||||
rt_kputs("\r\n");
|
||||
}
|
||||
|
||||
static void _assert_backtrace_cb(const char *ex, const char *func, rt_size_t line)
|
||||
{
|
||||
rt_hw_interrupt_disable();
|
||||
rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex, func, line);
|
||||
|
||||
rt_hw_backtrace(0, 0);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
static int rt_hw_backtrace_init(void)
|
||||
{
|
||||
rt_assert_set_hook(_assert_backtrace_cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_BOARD_EXPORT(rt_hw_backtrace_init);
|
||||
|
||||
static void backtrace_test(int args, char *argv[])
|
||||
{
|
||||
int *p = (void *)-1;
|
||||
init_fn_t ft = 0;
|
||||
|
||||
if (args < 2)
|
||||
{
|
||||
rt_kprintf("backtrace_test usage:backtrace_test a(assert)/m(invalid memory)/i(illegal instruction)\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rt_strcmp(argv[1], "a"))
|
||||
{
|
||||
rt_kprintf("Assert test:\r\n", argv[1]);
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
else if (!rt_strcmp(argv[1], "m"))
|
||||
{
|
||||
rt_kprintf("Access invalid memory:\r\n", argv[1]);
|
||||
*p = 0;
|
||||
}
|
||||
else if (!rt_strcmp(argv[1], "i"))
|
||||
{
|
||||
rt_kprintf("Illegal instruction:\r\n", argv[1]);
|
||||
ft();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("Unknown cmd :%s.\r\n", argv[1]);
|
||||
}
|
||||
}
|
||||
MSH_CMD_EXPORT(backtrace_test, backtrace test case);
|
||||
|
||||
extern struct rt_thread *rt_current_thread;
|
||||
|
||||
#define IN_USERSPACE (sepc > USER_VADDR_START && sepc < USER_VADDR_TOP)
|
||||
|
||||
static char *_get_elf_name(size_t sepc)
|
||||
{
|
||||
return IN_USERSPACE ? rt_current_thread->name : "rtthread.elf";
|
||||
}
|
||||
|
||||
#endif /* RT_USING_SMART */
|
||||
@@ -23,7 +23,7 @@ rt_hw_context_switch_to:
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
mv a0, s1
|
||||
jal lwp_mmu_switch
|
||||
jal lwp_aspace_switch
|
||||
#endif
|
||||
|
||||
RESTORE_ALL
|
||||
@@ -56,7 +56,7 @@ rt_hw_context_switch:
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
mv a0, s1
|
||||
jal lwp_mmu_switch
|
||||
jal lwp_aspace_switch
|
||||
#endif
|
||||
|
||||
RESTORE_ALL
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "cpuport.h"
|
||||
#include "sbi.h"
|
||||
#include "stack.h"
|
||||
|
||||
#include <lwp_arch.h>
|
||||
@@ -110,10 +111,8 @@ void rt_hw_cpu_shutdown()
|
||||
rt_kprintf("shutdown...\n");
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
sbi_shutdown();
|
||||
while (1);
|
||||
}
|
||||
|
||||
int rt_hw_cpu_id(void)
|
||||
|
||||
@@ -37,19 +37,21 @@
|
||||
#define CTX_REG_NR (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <rtthread.h>
|
||||
|
||||
rt_inline void rt_hw_dsb()
|
||||
{
|
||||
asm volatile("fence":::"memory");
|
||||
__asm__ volatile("fence":::"memory");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_dmb()
|
||||
{
|
||||
asm volatile("fence":::"memory");
|
||||
__asm__ volatile("fence":::"memory");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_isb()
|
||||
{
|
||||
asm volatile(OPC_FENCE_I:::"memory");
|
||||
__asm__ volatile(OPC_FENCE_I:::"memory");
|
||||
}
|
||||
|
||||
int rt_hw_cpu_id(void);
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#define SSTATUS_FS_CLEAN 0x00004000
|
||||
#define SSTATUS_FS_DIRTY 0x00006000
|
||||
#define SSTATUS_XS 0x00018000
|
||||
#define SSTATUS_PUM 0x00040000
|
||||
#define SSTATUS_SUM 0x00040000
|
||||
#define SSTATUS32_SD 0x80000000
|
||||
#define SSTATUS64_SD 0x8000000000000000
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ copy_context_loop_interrupt:
|
||||
#ifdef RT_USING_SMART
|
||||
mv a0, s1
|
||||
jal rt_thread_sp_to_thread
|
||||
jal lwp_mmu_switch
|
||||
jal lwp_aspace_switch
|
||||
#endif
|
||||
|
||||
spurious_interrupt:
|
||||
|
||||
+421
-551
File diff suppressed because it is too large
Load Diff
@@ -13,45 +13,83 @@
|
||||
|
||||
#include "riscv.h"
|
||||
#include "riscv_mmu.h"
|
||||
#include <mm_aspace.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* RAM, Flash, or ROM */
|
||||
#define NORMAL_MEM 0
|
||||
/* normal nocache memory mapping type */
|
||||
#define NORMAL_NOCACHE_MEM 1
|
||||
/* MMIO region */
|
||||
#define DEVICE_MEM 2
|
||||
|
||||
typedef size_t rt_pte_t;
|
||||
|
||||
struct mem_desc
|
||||
{
|
||||
rt_size_t vaddr_start;
|
||||
rt_size_t vaddr_end;
|
||||
rt_size_t paddr_start;
|
||||
rt_size_t attr;
|
||||
struct rt_varea varea;
|
||||
};
|
||||
|
||||
#define GET_PF_ID(addr) ((addr) >> PAGE_OFFSET_BIT)
|
||||
#define GET_PF_OFFSET(addr) __MASKVALUE(addr,PAGE_OFFSET_MASK)
|
||||
#define GET_L1(addr) __PARTBIT(addr,VPN2_SHIFT,VPN2_BIT)
|
||||
#define GET_L2(addr) __PARTBIT(addr,VPN1_SHIFT,VPN1_BIT)
|
||||
#define GET_L3(addr) __PARTBIT(addr,VPN0_SHIFT,VPN0_BIT)
|
||||
#define GET_PPN(pte) (__PARTBIT(pte,PTE_PPN_SHIFT,PHYSICAL_ADDRESS_WIDTH_BITS - PTE_PPN_SHIFT))
|
||||
#define GET_PADDR(pte) (GET_PPN(pte) << PAGE_OFFSET_BIT)
|
||||
#define VPN_TO_PPN(vaddr,pv_off) (((rt_size_t)(vaddr)) + (pv_off))
|
||||
#define PPN_TO_VPN(paddr,pv_off) (((rt_size_t)(paddr)) - (pv_off))
|
||||
#define COMBINEVADDR(l1_off,l2_off,l3_off) (((l1_off) << VPN2_SHIFT) | ((l2_off) << VPN1_SHIFT) | ((l3_off) << VPN0_SHIFT))
|
||||
#define COMBINEPTE(paddr,attr) ((((paddr) >> PAGE_OFFSET_BIT) << PTE_PPN_SHIFT) | (attr))
|
||||
#define GET_PF_ID(addr) ((addr) >> PAGE_OFFSET_BIT)
|
||||
#define GET_PF_OFFSET(addr) __MASKVALUE(addr, PAGE_OFFSET_MASK)
|
||||
#define GET_L1(addr) __PARTBIT(addr, VPN2_SHIFT, VPN2_BIT)
|
||||
#define GET_L2(addr) __PARTBIT(addr, VPN1_SHIFT, VPN1_BIT)
|
||||
#define GET_L3(addr) __PARTBIT(addr, VPN0_SHIFT, VPN0_BIT)
|
||||
#define GET_PPN(pte) \
|
||||
(__PARTBIT(pte, PTE_PPN_SHIFT, PHYSICAL_ADDRESS_WIDTH_BITS - PTE_PPN_SHIFT))
|
||||
#define GET_PADDR(pte) (GET_PPN(pte) << PAGE_OFFSET_BIT)
|
||||
#define VPN_TO_PPN(vaddr, pv_off) (((rt_size_t)(vaddr)) + (pv_off))
|
||||
#define PPN_TO_VPN(paddr, pv_off) (((rt_size_t)(paddr)) - (pv_off))
|
||||
#define COMBINEVADDR(l1_off, l2_off, l3_off) \
|
||||
(((l1_off) << VPN2_SHIFT) | ((l2_off) << VPN1_SHIFT) | \
|
||||
((l3_off) << VPN0_SHIFT))
|
||||
#define COMBINEPTE(paddr, attr) \
|
||||
((((paddr) >> PAGE_OFFSET_BIT) << PTE_PPN_SHIFT) | (attr))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t *vtable;
|
||||
size_t vstart;
|
||||
size_t vend;
|
||||
size_t pv_off;
|
||||
}rt_mmu_info;
|
||||
#define ARCH_ADDRESS_WIDTH_BITS 64
|
||||
|
||||
#define MMU_MAP_ERROR_VANOTALIGN -1
|
||||
#define MMU_MAP_ERROR_PANOTALIGN -2
|
||||
#define MMU_MAP_ERROR_NOPAGE -3
|
||||
#define MMU_MAP_ERROR_CONFLICT -4
|
||||
|
||||
void *rt_hw_mmu_tbl_get();
|
||||
void rt_hw_mmu_switch(void *mmu_table);
|
||||
int rt_hw_mmu_map_init(rt_mmu_info *mmu_info,void *v_address,rt_size_t size,rt_size_t *vtable,rt_size_t pv_off);
|
||||
void rt_hw_mmu_kernel_map_init(rt_mmu_info *mmu_info,rt_size_t vaddr_start,rt_size_t size);
|
||||
void *_rt_hw_mmu_map(rt_mmu_info *mmu_info,void *v_addr,void *p_addr,rt_size_t size,rt_size_t attr);
|
||||
void *_rt_hw_mmu_map_auto(rt_mmu_info *mmu_info,void *v_addr,rt_size_t size,rt_size_t attr);
|
||||
void _rt_hw_mmu_unmap(rt_mmu_info *mmu_info,void *v_addr,rt_size_t size);
|
||||
void *rt_hw_mmu_map(rt_mmu_info *mmu_info,void *v_addr,void *p_addr,rt_size_t size,rt_size_t attr);
|
||||
void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info,void *v_addr,rt_size_t size,rt_size_t attr);
|
||||
void rt_hw_mmu_unmap(rt_mmu_info *mmu_info,void *v_addr,rt_size_t size);
|
||||
void *_rt_hw_mmu_v2p(rt_mmu_info *mmu_info,void *v_addr);
|
||||
void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info,void *v_addr);
|
||||
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);
|
||||
void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr);
|
||||
void rt_hw_mmu_kernel_map_init(rt_aspace_t aspace, rt_size_t vaddr_start,
|
||||
rt_size_t size);
|
||||
void *rt_hw_mmu_map(rt_aspace_t aspace, void *v_addr, void *p_addr, size_t size,
|
||||
size_t attr);
|
||||
void rt_hw_mmu_unmap(rt_aspace_t aspace, void *v_addr, size_t size);
|
||||
void rt_hw_aspace_switch(rt_aspace_t aspace);
|
||||
void *rt_hw_mmu_v2p(rt_aspace_t aspace, void *vaddr);
|
||||
|
||||
static inline void *_rt_kmem_v2p(void *vaddr)
|
||||
{
|
||||
return rt_hw_mmu_v2p(&rt_kernel_space, vaddr);
|
||||
}
|
||||
|
||||
static inline void *rt_kmem_v2p(void *vaddr)
|
||||
{
|
||||
MM_PGTBL_LOCK(&rt_kernel_space);
|
||||
void *paddr = _rt_kmem_v2p(vaddr);
|
||||
MM_PGTBL_UNLOCK(&rt_kernel_space);
|
||||
return paddr;
|
||||
}
|
||||
|
||||
enum rt_mmu_cntl
|
||||
{
|
||||
MMU_CNTL_NONCACHE,
|
||||
MMU_CNTL_CACHE,
|
||||
MMU_CNTL_DUMMY_END,
|
||||
};
|
||||
|
||||
int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size,
|
||||
enum rt_mmu_cntl cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,20 +18,12 @@
|
||||
|
||||
#include "riscv_mmu.h"
|
||||
|
||||
void mmu_set_pagetable(rt_ubase_t addr)
|
||||
{
|
||||
RT_ASSERT(__CHECKALIGN(addr,PAGE_OFFSET_BIT));
|
||||
RT_ASSERT(__CHECKUPBOUND(addr,PHYSICAL_ADDRESS_WIDTH_BITS));
|
||||
write_csr(satp,(((size_t)8) << 60) | (addr >> PAGE_OFFSET_BIT));
|
||||
mmu_flush_tlb();
|
||||
}
|
||||
|
||||
void mmu_enable_user_page_access()
|
||||
{
|
||||
set_csr(sstatus,SSTATUS_PUM);
|
||||
set_csr(sstatus,SSTATUS_SUM);
|
||||
}
|
||||
|
||||
void mmu_disable_user_page_access()
|
||||
{
|
||||
clear_csr(sstatus,SSTATUS_PUM);
|
||||
clear_csr(sstatus,SSTATUS_SUM);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#ifndef __RISCV_MMU_H__
|
||||
#define __RISCV_MMU_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include "riscv.h"
|
||||
|
||||
#undef PAGE_SIZE
|
||||
@@ -59,21 +59,42 @@
|
||||
#define PAGE_ATTR_USER (PTE_U)
|
||||
#define PAGE_ATTR_SYSTEM (0)
|
||||
|
||||
#define PAGE_DEFAULT_ATTR_LEAF (PAGE_ATTR_RWX | PAGE_ATTR_USER | PTE_V | PTE_G | PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D)
|
||||
#define PAGE_DEFAULT_ATTR_NEXT (PAGE_ATTR_NEXT_LEVEL | PTE_V | PTE_G | PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D)
|
||||
#define PAGE_DEFAULT_ATTR_LEAF (PAGE_ATTR_RWX | PAGE_ATTR_USER | PTE_V | PTE_G)
|
||||
#define PAGE_DEFAULT_ATTR_NEXT (PAGE_ATTR_NEXT_LEVEL | PTE_V | PTE_G)
|
||||
|
||||
#define PAGE_IS_LEAF(pte) __MASKVALUE(pte,PAGE_ATTR_RWX)
|
||||
#define PAGE_IS_LEAF(pte) __MASKVALUE(pte, PAGE_ATTR_RWX)
|
||||
|
||||
#define PTE_USED(pte) __MASKVALUE(pte,PTE_V)
|
||||
#define PTE_USED(pte) __MASKVALUE(pte, PTE_V)
|
||||
|
||||
#define mmu_flush_tlb() do{asm volatile("sfence.vma x0,x0");}while(0)
|
||||
/**
|
||||
* encoding of SATP (Supervisor Address Translation and Protection register)
|
||||
*/
|
||||
#define SATP_MODE_OFFSET 60
|
||||
#define SATP_MODE_BARE 0
|
||||
#define SATP_MODE_SV39 8
|
||||
#define SATP_MODE_SV48 9
|
||||
#define SATP_MODE_SV57 10
|
||||
#define SATP_MODE_SV64 11
|
||||
|
||||
//compatible to rt-smart new version
|
||||
#define MMU_MAP_K_DEVICE (PAGE_ATTR_RWX | PTE_V | PTE_G | PTE_SO | PTE_BUF | PTE_A | PTE_D)
|
||||
#define MMU_MAP_K_RWCB (PAGE_ATTR_RWX | PTE_V | PTE_G | PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D)
|
||||
#define ARCH_PAGE_SIZE PAGE_SIZE
|
||||
#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1)
|
||||
#define ARCH_PAGE_SHIFT PAGE_OFFSET_BIT
|
||||
#define ARCH_VADDR_WIDTH 39
|
||||
#define SATP_MODE SATP_MODE_SV39
|
||||
|
||||
#define MMU_MAP_K_DEVICE (PTE_G | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_K_RWCB (PTE_G | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_U_RWCB (PTE_U | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_U_RWCB_XN (PTE_U | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_U_RW (PTE_U | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
|
||||
#define PTE_XWR_MASK 0xe
|
||||
|
||||
#define ARCH_PAGE_SIZE PAGE_SIZE
|
||||
#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1)
|
||||
#define ARCH_PAGE_SHIFT PAGE_OFFSET_BIT
|
||||
#define ARCH_INDEX_WIDTH 9
|
||||
#define ARCH_INDEX_SIZE (1ul << ARCH_INDEX_WIDTH)
|
||||
#define ARCH_INDEX_MASK (ARCH_INDEX_SIZE - 1)
|
||||
|
||||
#define ARCH_MAP_FAILED ((void *)0x8000000000000000)
|
||||
|
||||
void mmu_set_pagetable(rt_ubase_t addr);
|
||||
void mmu_enable_user_page_access();
|
||||
|
||||
@@ -36,12 +36,12 @@
|
||||
*/
|
||||
|
||||
#include "sbi.h"
|
||||
#include <stdbool.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* SBI Implementation-Specific Definitions */
|
||||
#define OPENSBI_VERSION_MAJOR_OFFSET 16
|
||||
#define OPENSBI_VERSION_MINOR_MASK 0xFFFF
|
||||
#define OPENSBI_VERSION_MAJOR_OFFSET 16
|
||||
#define OPENSBI_VERSION_MINOR_MASK 0xFFFF
|
||||
|
||||
unsigned long sbi_spec_version;
|
||||
unsigned long sbi_impl_id;
|
||||
@@ -51,26 +51,22 @@ static bool has_time_extension = false;
|
||||
static bool has_ipi_extension = false;
|
||||
static bool has_rfnc_extension = false;
|
||||
|
||||
static struct sbi_ret
|
||||
sbi_get_spec_version(void)
|
||||
static struct sbi_ret sbi_get_spec_version(void)
|
||||
{
|
||||
return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_SPEC_VERSION));
|
||||
}
|
||||
|
||||
static struct sbi_ret
|
||||
sbi_get_impl_id(void)
|
||||
static struct sbi_ret sbi_get_impl_id(void)
|
||||
{
|
||||
return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_ID));
|
||||
}
|
||||
|
||||
static struct sbi_ret
|
||||
sbi_get_impl_version(void)
|
||||
static struct sbi_ret sbi_get_impl_version(void)
|
||||
{
|
||||
return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_VERSION));
|
||||
}
|
||||
|
||||
void
|
||||
sbi_print_version(void)
|
||||
void sbi_print_version(void)
|
||||
{
|
||||
u_int major;
|
||||
u_int minor;
|
||||
@@ -89,7 +85,8 @@ sbi_print_version(void)
|
||||
rt_kprintf("SBI: Berkely Boot Loader %lu\n", sbi_impl_version);
|
||||
break;
|
||||
case (SBI_IMPL_ID_XVISOR):
|
||||
rt_kprintf("SBI: eXtensible Versatile hypervISOR %lu\n", sbi_impl_version);
|
||||
rt_kprintf("SBI: eXtensible Versatile hypervISOR %lu\n",
|
||||
sbi_impl_version);
|
||||
break;
|
||||
case (SBI_IMPL_ID_KVM):
|
||||
rt_kprintf("SBI: Kernel-based Virtual Machine %lu\n", sbi_impl_version);
|
||||
@@ -116,8 +113,7 @@ sbi_print_version(void)
|
||||
rt_kprintf("SBI Specification Version: %u.%u\n", major, minor);
|
||||
}
|
||||
|
||||
void
|
||||
sbi_set_timer(uint64_t val)
|
||||
void sbi_set_timer(uint64_t val)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
|
||||
@@ -133,16 +129,14 @@ sbi_set_timer(uint64_t val)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sbi_send_ipi(const unsigned long *hart_mask)
|
||||
void sbi_send_ipi(const unsigned long *hart_mask)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
|
||||
/* Use the IPI legacy replacement extension, if available. */
|
||||
if (has_ipi_extension)
|
||||
{
|
||||
ret = SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI,
|
||||
*hart_mask, 0);
|
||||
ret = SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI, *hart_mask, 0);
|
||||
RT_ASSERT(ret.error == SBI_SUCCESS);
|
||||
}
|
||||
else
|
||||
@@ -151,16 +145,15 @@ sbi_send_ipi(const unsigned long *hart_mask)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sbi_remote_fence_i(const unsigned long *hart_mask)
|
||||
void sbi_remote_fence_i(const unsigned long *hart_mask)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
|
||||
/* Use the RFENCE legacy replacement extension, if available. */
|
||||
if (has_rfnc_extension)
|
||||
{
|
||||
ret = SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I,
|
||||
*hart_mask, 0);
|
||||
ret =
|
||||
SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I, *hart_mask, 0);
|
||||
RT_ASSERT(ret.error == SBI_SUCCESS);
|
||||
}
|
||||
else
|
||||
@@ -169,28 +162,29 @@ sbi_remote_fence_i(const unsigned long *hart_mask)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sbi_remote_sfence_vma(const unsigned long *hart_mask, unsigned long start, unsigned long size)
|
||||
int sbi_remote_sfence_vma(const unsigned long *hart_mask,
|
||||
const unsigned long hart_mask_base,
|
||||
unsigned long start, unsigned long size)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
struct sbi_ret ret = {.error = SBI_SUCCESS};
|
||||
|
||||
/* Use the RFENCE legacy replacement extension, if available. */
|
||||
if (has_rfnc_extension)
|
||||
{
|
||||
ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA,
|
||||
*hart_mask, 0, start, size);
|
||||
RT_ASSERT(ret.error == SBI_SUCCESS);
|
||||
ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA, *hart_mask,
|
||||
hart_mask_base, start, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask,
|
||||
start, size);
|
||||
(void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, start,
|
||||
size);
|
||||
}
|
||||
return ret.error;
|
||||
}
|
||||
|
||||
void
|
||||
sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start, unsigned long size,
|
||||
unsigned long asid)
|
||||
void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
|
||||
unsigned long start, unsigned long size,
|
||||
unsigned long asid)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
|
||||
@@ -203,13 +197,13 @@ sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start,
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0,
|
||||
(uint64_t)hart_mask, start, size, asid);
|
||||
(void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, (uint64_t)hart_mask,
|
||||
start, size, asid);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr, unsigned long priv)
|
||||
int sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr,
|
||||
unsigned long priv)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
|
||||
@@ -217,14 +211,12 @@ sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr, unsigned long p
|
||||
return (ret.error != 0 ? (int)ret.error : 0);
|
||||
}
|
||||
|
||||
void
|
||||
sbi_hsm_hart_stop(void)
|
||||
void sbi_hsm_hart_stop(void)
|
||||
{
|
||||
(void)SBI_CALL0(SBI_EXT_ID_HSM, SBI_HSM_HART_STOP);
|
||||
}
|
||||
|
||||
int
|
||||
sbi_hsm_hart_status(unsigned long hart)
|
||||
int sbi_hsm_hart_status(unsigned long hart)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
|
||||
@@ -233,8 +225,7 @@ sbi_hsm_hart_status(unsigned long hart)
|
||||
return (ret.error != 0 ? (int)ret.error : (int)ret.value);
|
||||
}
|
||||
|
||||
void
|
||||
sbi_init(void)
|
||||
void sbi_init(void)
|
||||
{
|
||||
struct sbi_ret sret;
|
||||
|
||||
@@ -263,3 +254,11 @@ sbi_init(void)
|
||||
if (sbi_probe_extension(SBI_EXT_ID_RFNC) != 0)
|
||||
has_rfnc_extension = true;
|
||||
}
|
||||
|
||||
void rt_hw_console_output(const char *str)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
sbi_console_putchar(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ struct sbi_ret
|
||||
long value;
|
||||
};
|
||||
|
||||
static __inline struct sbi_ret
|
||||
static inline struct sbi_ret
|
||||
sbi_call(uint64_t arg7, uint64_t arg6, uint64_t arg0, uint64_t arg1,
|
||||
uint64_t arg2, uint64_t arg3, uint64_t arg4)
|
||||
{
|
||||
@@ -184,7 +184,9 @@ void sbi_send_ipi(const unsigned long *hart_mask);
|
||||
|
||||
/* RFENCE extension functions. */
|
||||
void sbi_remote_fence_i(const unsigned long *hart_mask);
|
||||
void sbi_remote_sfence_vma(const unsigned long *hart_mask, unsigned long start, unsigned long size);
|
||||
int sbi_remote_sfence_vma(const unsigned long *hart_mask,
|
||||
const unsigned long hart_mask_base,
|
||||
unsigned long start, unsigned long size);
|
||||
void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start,
|
||||
unsigned long size, unsigned long asid);
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-11-28 WangXiaoyao the first version
|
||||
*/
|
||||
#ifndef __TLB_H__
|
||||
#define __TLB_H__
|
||||
|
||||
#include "mm_aspace.h"
|
||||
#include "riscv_mmu.h"
|
||||
#include "rtdbg.h"
|
||||
#include "rtthread.h"
|
||||
#include <sbi.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define HANDLE_FAULT(ret) \
|
||||
if (__builtin_expect((ret) != SBI_SUCCESS, 0)) \
|
||||
LOG_W("%s failed", __FUNCTION__);
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_all(void)
|
||||
{
|
||||
uintptr_t mask = -1ul;
|
||||
HANDLE_FAULT(sbi_remote_sfence_vma(&mask, -1ul, 0, mask));
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_all_local(void)
|
||||
{
|
||||
__asm__ volatile("sfence.vma" ::: "memory");
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_aspace(rt_aspace_t aspace)
|
||||
{
|
||||
// TODO ASID
|
||||
rt_hw_tlb_invalidate_all_local();
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_page(rt_aspace_t aspace, void *start)
|
||||
{
|
||||
__asm__ volatile("sfence.vma %0, zero" ::"r"(start) : "memory");
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_range(rt_aspace_t aspace, void *start,
|
||||
size_t size, size_t stride)
|
||||
{
|
||||
// huge page is taking as normal page
|
||||
if (size <= ARCH_PAGE_SIZE)
|
||||
{
|
||||
rt_hw_tlb_invalidate_page(aspace, start);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_tlb_invalidate_aspace(aspace);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __TLB_H__ */
|
||||
@@ -107,7 +107,7 @@ void dump_regs(struct rt_hw_stack_frame *regs)
|
||||
rt_kprintf("\t%s\n",(regs->sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
|
||||
rt_kprintf("\t%s\n",(regs->sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
|
||||
rt_kprintf("\t%s\n",(regs->sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
|
||||
rt_kprintf("\t%s\n",(regs->sstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
|
||||
rt_kprintf("\t%s\n",(regs->sstatus & SSTATUS_SUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
|
||||
rt_kprintf("\t%s\n",(regs->sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
|
||||
rt_size_t satp_v = read_csr(satp);
|
||||
rt_kprintf("satp = 0x%p\n",satp_v);
|
||||
@@ -202,6 +202,45 @@ void generic_handle_irq(int irq)
|
||||
plic_complete(irq);
|
||||
}
|
||||
|
||||
static const char *get_exception_msg(int id)
|
||||
{
|
||||
const char *msg;
|
||||
if (id < sizeof(Exception_Name) / sizeof(const char *))
|
||||
{
|
||||
msg = Exception_Name[id];
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Unknown Exception";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp)
|
||||
{
|
||||
rt_size_t id = __MASKVALUE(scause, __MASK(63UL));
|
||||
|
||||
#ifdef RT_USING_USERSPACE
|
||||
/* user page fault */
|
||||
if (id == EP_LOAD_PAGE_FAULT ||
|
||||
id == EP_STORE_PAGE_FAULT)
|
||||
{
|
||||
if (arch_expand_user_stack((void *)stval))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LOG_E("[FATAL ERROR] Exception %ld:%s", id, get_exception_msg(id));
|
||||
LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p", scause, stval, sepc);
|
||||
dump_regs(sp);
|
||||
|
||||
rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
|
||||
|
||||
LOG_E("User Fault, killing thread: %s", rt_thread_self()->name);
|
||||
sys_exit(-1);
|
||||
}
|
||||
|
||||
/* Trap entry */
|
||||
void handle_trap(rt_size_t scause,rt_size_t stval,rt_size_t sepc,struct rt_hw_stack_frame *sp)
|
||||
{
|
||||
@@ -238,28 +277,28 @@ void handle_trap(rt_size_t scause,rt_size_t stval,rt_size_t sepc,struct rt_hw_st
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef RT_USING_SMART
|
||||
/* page fault */
|
||||
if (id == EP_LOAD_PAGE_FAULT ||
|
||||
id == EP_STORE_PAGE_FAULT)
|
||||
if (!(sp->sstatus & 0x100))
|
||||
{
|
||||
arch_expand_user_stack((void *)stval);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(id < sizeof(Exception_Name) / sizeof(const char *))
|
||||
{
|
||||
msg = Exception_Name[id];
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Unknown Exception";
|
||||
handle_user(scause, stval, sepc, sp);
|
||||
// after handle_user(), return to user space.
|
||||
// otherwise it never returns
|
||||
return ;
|
||||
}
|
||||
|
||||
rt_kprintf("Unhandled Exception %ld:%s\n",id,msg);
|
||||
// handle kernel exception:
|
||||
rt_kprintf("Unhandled Exception %ld:%s\n", id, get_exception_msg(id));
|
||||
}
|
||||
|
||||
rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n",scause,stval,sepc);
|
||||
rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
||||
dump_regs(sp);
|
||||
while(1);
|
||||
rt_kprintf("--------------Thread list--------------\n");
|
||||
rt_kprintf("current thread: %s\n", rt_thread_self()->name);
|
||||
list_process();
|
||||
|
||||
extern struct rt_thread *rt_current_thread;
|
||||
rt_kprintf("--------------Backtrace--------------\n");
|
||||
rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
extern rt_ubase_t __text_start[];
|
||||
extern rt_ubase_t __text_end[];
|
||||
|
||||
static char *_get_elf_name();
|
||||
static char *_get_elf_name(size_t sepc);
|
||||
|
||||
void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc)
|
||||
{
|
||||
extern rt_mmu_info mmu_info;
|
||||
rt_ubase_t *ra;
|
||||
rt_ubase_t *fp;
|
||||
rt_ubase_t vas, vae;
|
||||
@@ -60,13 +59,13 @@ void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc)
|
||||
}
|
||||
|
||||
ra = fp - 1;
|
||||
if (!_rt_hw_mmu_v2p(&mmu_info, ra) || *ra < vas || *ra > vae)
|
||||
if (!_rt_kmem_v2p(ra) || *ra < vas || *ra > vae)
|
||||
break;
|
||||
|
||||
rt_kprintf(" %p", *ra - 0x04);
|
||||
|
||||
fp = fp - 2;
|
||||
if (!_rt_hw_mmu_v2p(&mmu_info, fp))
|
||||
if (!_rt_kmem_v2p(fp))
|
||||
break;
|
||||
fp = (rt_ubase_t *)(*fp);
|
||||
if (!fp)
|
||||
|
||||
@@ -80,7 +80,7 @@ rt_hw_context_switch_to:
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
mv a0, s1
|
||||
jal lwp_mmu_switch
|
||||
jal lwp_aspace_switch
|
||||
#endif
|
||||
|
||||
RESTORE_CONTEXT
|
||||
@@ -108,7 +108,7 @@ rt_hw_context_switch:
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
mv a0, s1
|
||||
jal lwp_mmu_switch
|
||||
jal lwp_aspace_switch
|
||||
#endif
|
||||
|
||||
RESTORE_CONTEXT
|
||||
|
||||
+355
-515
File diff suppressed because it is too large
Load Diff
+52
-38
@@ -13,13 +13,17 @@
|
||||
|
||||
#include "riscv.h"
|
||||
#include "riscv_mmu.h"
|
||||
#include <mm_aspace.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* RAM, Flash, or ROM */
|
||||
#define NORMAL_MEM 0
|
||||
#define NORMAL_MEM 0
|
||||
/* normal nocache memory mapping type */
|
||||
#define NORMAL_NOCACHE_MEM 1
|
||||
#define NORMAL_NOCACHE_MEM 1
|
||||
/* MMIO region */
|
||||
#define DEVICE_MEM 2
|
||||
#define DEVICE_MEM 2
|
||||
|
||||
typedef size_t rt_pte_t;
|
||||
|
||||
struct mem_desc
|
||||
{
|
||||
@@ -27,48 +31,58 @@ struct mem_desc
|
||||
rt_size_t vaddr_end;
|
||||
rt_size_t paddr_start;
|
||||
rt_size_t attr;
|
||||
struct rt_varea varea;
|
||||
};
|
||||
|
||||
#define GET_PF_ID(addr) ((addr) >> PAGE_OFFSET_BIT)
|
||||
#define GET_PF_ID(addr) ((addr) >> PAGE_OFFSET_BIT)
|
||||
#define GET_PF_OFFSET(addr) __MASKVALUE(addr, PAGE_OFFSET_MASK)
|
||||
#define GET_L1(addr) __PARTBIT(addr, VPN2_SHIFT, VPN2_BIT)
|
||||
#define GET_L2(addr) __PARTBIT(addr, VPN1_SHIFT, VPN1_BIT)
|
||||
#define GET_L3(addr) __PARTBIT(addr, VPN0_SHIFT, VPN0_BIT)
|
||||
#define GET_PPN(pte) (__PARTBIT(pte, PTE_PPN_SHIFT, PHYSICAL_ADDRESS_WIDTH_BITS - PTE_PPN_SHIFT))
|
||||
#define GET_PADDR(pte) (GET_PPN(pte) << PAGE_OFFSET_BIT)
|
||||
#define GET_L1(addr) __PARTBIT(addr, VPN2_SHIFT, VPN2_BIT)
|
||||
#define GET_L2(addr) __PARTBIT(addr, VPN1_SHIFT, VPN1_BIT)
|
||||
#define GET_L3(addr) __PARTBIT(addr, VPN0_SHIFT, VPN0_BIT)
|
||||
#define GET_PPN(pte) \
|
||||
(__PARTBIT(pte, PTE_PPN_SHIFT, PHYSICAL_ADDRESS_WIDTH_BITS - PTE_PPN_SHIFT))
|
||||
#define GET_PADDR(pte) (GET_PPN(pte) << PAGE_OFFSET_BIT)
|
||||
#define VPN_TO_PPN(vaddr, pv_off) (((rt_size_t)(vaddr)) + (pv_off))
|
||||
#define PPN_TO_VPN(paddr, pv_off) (((rt_size_t)(paddr)) - (pv_off))
|
||||
#define COMBINEVADDR(l1_off, l2_off, l3_off) (((l1_off) << VPN2_SHIFT) | ((l2_off) << VPN1_SHIFT) | ((l3_off) << VPN0_SHIFT))
|
||||
#define COMBINEPTE(paddr, attr) ((((paddr) >> PAGE_OFFSET_BIT) << PTE_PPN_SHIFT) | (attr))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t *vtable;
|
||||
size_t vstart;
|
||||
size_t vend;
|
||||
size_t pv_off;
|
||||
} rt_mmu_info;
|
||||
|
||||
void *rt_hw_mmu_tbl_get();
|
||||
void rt_hw_mmu_switch(void *mmu_table);
|
||||
int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void *v_address, rt_size_t size, rt_size_t *vtable, rt_size_t pv_off);
|
||||
void rt_hw_mmu_kernel_map_init(rt_mmu_info *mmu_info, rt_size_t vaddr_start, rt_size_t size);
|
||||
void *_rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void *p_addr, rt_size_t size, rt_size_t attr);
|
||||
void *_rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, rt_size_t size, rt_size_t attr);
|
||||
void _rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void *v_addr, rt_size_t size);
|
||||
void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void *p_addr, rt_size_t size, rt_size_t attr);
|
||||
void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, rt_size_t size, rt_size_t attr);
|
||||
void rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void *v_addr, rt_size_t size);
|
||||
void *_rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void *v_addr);
|
||||
void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void *v_addr);
|
||||
|
||||
void rt_hw_mmu_setup(rt_mmu_info *mmu_info, struct mem_desc *mdesc, int desc_nr);
|
||||
#define COMBINEVADDR(l1_off, l2_off, l3_off) \
|
||||
(((l1_off) << VPN2_SHIFT) | ((l2_off) << VPN1_SHIFT) | \
|
||||
((l3_off) << VPN0_SHIFT))
|
||||
#define COMBINEPTE(paddr, attr) \
|
||||
((((paddr) >> PAGE_OFFSET_BIT) << PTE_PPN_SHIFT) | (attr))
|
||||
|
||||
#define ARCH_ADDRESS_WIDTH_BITS 64
|
||||
|
||||
#define MMU_MAP_ERROR_VANOTALIGN -1
|
||||
#define MMU_MAP_ERROR_PANOTALIGN -2
|
||||
#define MMU_MAP_ERROR_NOPAGE -3
|
||||
#define MMU_MAP_ERROR_CONFLICT -4
|
||||
#define MMU_MAP_ERROR_VANOTALIGN -1
|
||||
#define MMU_MAP_ERROR_PANOTALIGN -2
|
||||
#define MMU_MAP_ERROR_NOPAGE -3
|
||||
#define MMU_MAP_ERROR_CONFLICT -4
|
||||
|
||||
void *rt_hw_mmu_tbl_get();
|
||||
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);
|
||||
void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr);
|
||||
void rt_hw_mmu_kernel_map_init(rt_aspace_t aspace, rt_size_t vaddr_start,
|
||||
rt_size_t size);
|
||||
void *rt_hw_mmu_map(rt_aspace_t aspace, void *v_addr, void *p_addr, size_t size,
|
||||
size_t attr);
|
||||
void rt_hw_mmu_unmap(rt_aspace_t aspace, void *v_addr, size_t size);
|
||||
void rt_hw_aspace_switch(rt_aspace_t aspace);
|
||||
void *rt_hw_mmu_v2p(rt_aspace_t aspace, void *vaddr);
|
||||
|
||||
static inline void *_rt_kmem_v2p(void *vaddr)
|
||||
{
|
||||
return rt_hw_mmu_v2p(&rt_kernel_space, vaddr);
|
||||
}
|
||||
|
||||
static inline void *rt_kmem_v2p(void *vaddr)
|
||||
{
|
||||
MM_PGTBL_LOCK(&rt_kernel_space);
|
||||
void *paddr = _rt_kmem_v2p(vaddr);
|
||||
MM_PGTBL_UNLOCK(&rt_kernel_space);
|
||||
return paddr;
|
||||
}
|
||||
|
||||
int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size,
|
||||
enum rt_mmu_cntl cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,23 +11,13 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <riscv.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "riscv_mmu.h"
|
||||
|
||||
void mmu_set_pagetable(rt_ubase_t addr)
|
||||
{
|
||||
RT_ASSERT(__CHECKALIGN(addr, PAGE_OFFSET_BIT));
|
||||
RT_ASSERT(__CHECKUPBOUND(addr, PHYSICAL_ADDRESS_WIDTH_BITS));
|
||||
|
||||
mmu_flush_tlb();
|
||||
write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) | (addr >> PAGE_OFFSET_BIT));
|
||||
mmu_flush_tlb();
|
||||
}
|
||||
|
||||
void mmu_enable_user_page_access()
|
||||
{
|
||||
set_csr(sstatus, SSTATUS_SUM);
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
#define PTE_USED(pte) __MASKVALUE(pte, PTE_V)
|
||||
|
||||
/**
|
||||
/**
|
||||
* encoding of SATP (Supervisor Address Translation and Protection register)
|
||||
*/
|
||||
#define SATP_MODE_OFFSET 60
|
||||
@@ -68,16 +68,9 @@
|
||||
#define SATP_MODE_SV57 10
|
||||
#define SATP_MODE_SV64 11
|
||||
|
||||
#define ARCH_VA_WIDTH 39
|
||||
#define ARCH_VADDR_WIDTH 39
|
||||
#define SATP_MODE SATP_MODE_SV39
|
||||
|
||||
#define mmu_flush_tlb() \
|
||||
do \
|
||||
{ \
|
||||
asm volatile("sfence.vma x0,x0"); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define MMU_MAP_K_DEVICE (PTE_G | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_K_RWCB (PTE_G | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_U_RWCB (PTE_U | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
@@ -93,6 +86,8 @@
|
||||
#define ARCH_INDEX_SIZE (1ul << ARCH_INDEX_WIDTH)
|
||||
#define ARCH_INDEX_MASK (ARCH_INDEX_SIZE - 1)
|
||||
|
||||
#define ARCH_MAP_FAILED ((void *)0x8000000000000000)
|
||||
|
||||
void mmu_set_pagetable(rt_ubase_t addr);
|
||||
void mmu_enable_user_page_access();
|
||||
void mmu_disable_user_page_access();
|
||||
|
||||
+24
-23
@@ -36,8 +36,8 @@
|
||||
*/
|
||||
|
||||
#include "sbi.h"
|
||||
#include <stdbool.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* SBI Implementation-Specific Definitions */
|
||||
#define OPENSBI_VERSION_MAJOR_OFFSET 16
|
||||
@@ -51,20 +51,17 @@ static bool has_time_extension = false;
|
||||
static bool has_ipi_extension = false;
|
||||
static bool has_rfnc_extension = false;
|
||||
|
||||
static struct sbi_ret
|
||||
sbi_get_spec_version(void)
|
||||
static struct sbi_ret sbi_get_spec_version(void)
|
||||
{
|
||||
return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_SPEC_VERSION));
|
||||
}
|
||||
|
||||
static struct sbi_ret
|
||||
sbi_get_impl_id(void)
|
||||
static struct sbi_ret sbi_get_impl_id(void)
|
||||
{
|
||||
return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_ID));
|
||||
}
|
||||
|
||||
static struct sbi_ret
|
||||
sbi_get_impl_version(void)
|
||||
static struct sbi_ret sbi_get_impl_version(void)
|
||||
{
|
||||
return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_VERSION));
|
||||
}
|
||||
@@ -88,7 +85,8 @@ void sbi_print_version(void)
|
||||
rt_kprintf("SBI: Berkely Boot Loader %lu\n", sbi_impl_version);
|
||||
break;
|
||||
case (SBI_IMPL_ID_XVISOR):
|
||||
rt_kprintf("SBI: eXtensible Versatile hypervISOR %lu\n", sbi_impl_version);
|
||||
rt_kprintf("SBI: eXtensible Versatile hypervISOR %lu\n",
|
||||
sbi_impl_version);
|
||||
break;
|
||||
case (SBI_IMPL_ID_KVM):
|
||||
rt_kprintf("SBI: Kernel-based Virtual Machine %lu\n", sbi_impl_version);
|
||||
@@ -138,8 +136,7 @@ void sbi_send_ipi(const unsigned long *hart_mask)
|
||||
/* Use the IPI legacy replacement extension, if available. */
|
||||
if (has_ipi_extension)
|
||||
{
|
||||
ret = SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI,
|
||||
*hart_mask, 0);
|
||||
ret = SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI, *hart_mask, 0);
|
||||
RT_ASSERT(ret.error == SBI_SUCCESS);
|
||||
}
|
||||
else
|
||||
@@ -155,8 +152,8 @@ void sbi_remote_fence_i(const unsigned long *hart_mask)
|
||||
/* Use the RFENCE legacy replacement extension, if available. */
|
||||
if (has_rfnc_extension)
|
||||
{
|
||||
ret = SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I,
|
||||
*hart_mask, 0);
|
||||
ret =
|
||||
SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I, *hart_mask, 0);
|
||||
RT_ASSERT(ret.error == SBI_SUCCESS);
|
||||
}
|
||||
else
|
||||
@@ -165,25 +162,28 @@ void sbi_remote_fence_i(const unsigned long *hart_mask)
|
||||
}
|
||||
}
|
||||
|
||||
void sbi_remote_sfence_vma(const unsigned long *hart_mask, unsigned long start, unsigned long size)
|
||||
int sbi_remote_sfence_vma(const unsigned long *hart_mask,
|
||||
const unsigned long hart_mask_base,
|
||||
unsigned long start, unsigned long size)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
struct sbi_ret ret = {.error = SBI_SUCCESS};
|
||||
|
||||
/* Use the RFENCE legacy replacement extension, if available. */
|
||||
if (has_rfnc_extension)
|
||||
{
|
||||
ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA,
|
||||
*hart_mask, 0, start, size);
|
||||
RT_ASSERT(ret.error == SBI_SUCCESS);
|
||||
ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA, *hart_mask,
|
||||
hart_mask_base, start, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask,
|
||||
start, size);
|
||||
(void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, start,
|
||||
size);
|
||||
}
|
||||
return ret.error;
|
||||
}
|
||||
|
||||
void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start, unsigned long size,
|
||||
void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
|
||||
unsigned long start, unsigned long size,
|
||||
unsigned long asid)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
@@ -197,12 +197,13 @@ void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long st
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0,
|
||||
(uint64_t)hart_mask, start, size, asid);
|
||||
(void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, (uint64_t)hart_mask,
|
||||
start, size, asid);
|
||||
}
|
||||
}
|
||||
|
||||
int sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr, unsigned long priv)
|
||||
int sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr,
|
||||
unsigned long priv)
|
||||
{
|
||||
struct sbi_ret ret;
|
||||
|
||||
|
||||
@@ -185,7 +185,9 @@ void sbi_send_ipi(const unsigned long *hart_mask);
|
||||
|
||||
/* RFENCE extension functions. */
|
||||
void sbi_remote_fence_i(const unsigned long *hart_mask);
|
||||
void sbi_remote_sfence_vma(const unsigned long *hart_mask, unsigned long start, unsigned long size);
|
||||
int sbi_remote_sfence_vma(const unsigned long *hart_mask,
|
||||
const unsigned long hart_mask_base,
|
||||
unsigned long start, unsigned long size);
|
||||
void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start,
|
||||
unsigned long size, unsigned long asid);
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-12-07 RT-Thread the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "board.h"
|
||||
|
||||
void init_bss(void)
|
||||
{
|
||||
unsigned int *dst;
|
||||
|
||||
dst = &__bss_start;
|
||||
while (dst < &__bss_end)
|
||||
{
|
||||
*dst++ = 0;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
* 2020/6/12 Xim Port to QEMU and remove SMP support
|
||||
*/
|
||||
|
||||
#define SSTATUS_FS 0x00006000U /* initial state of FPU, clear to disable */
|
||||
#include <encoding.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
boot_hartid: .int
|
||||
@@ -72,7 +72,7 @@ _start:
|
||||
li x31,0
|
||||
|
||||
/* set to disable FPU */
|
||||
li t0, SSTATUS_FS
|
||||
li t0, SSTATUS_FS + SSTATUS_VS
|
||||
csrc sstatus, t0
|
||||
li t0, 0x40000 // SUM in sstatus
|
||||
csrs sstatus, t0
|
||||
@@ -91,4 +91,6 @@ _start:
|
||||
* sscratch is always zero on kernel mode
|
||||
*/
|
||||
csrw sscratch, zero
|
||||
call init_bss
|
||||
call sbi_init
|
||||
j primary_cpu_entry
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <stdint.h>
|
||||
#include <mmu.h>
|
||||
#include <page.h>
|
||||
#include <lwp_mm_area.h>
|
||||
#include <lwp_user_mm.h>
|
||||
|
||||
#include "riscv_mmu.h"
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-11-28 WangXiaoyao the first version
|
||||
*/
|
||||
#ifndef __TLB_H__
|
||||
#define __TLB_H__
|
||||
|
||||
#include "mm_aspace.h"
|
||||
#include "riscv_mmu.h"
|
||||
#include "rtdbg.h"
|
||||
#include "rtthread.h"
|
||||
#include <sbi.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define HANDLE_FAULT(ret) \
|
||||
if (__builtin_expect((ret) != SBI_SUCCESS, 0)) \
|
||||
LOG_W("%s failed", __FUNCTION__);
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_all(void)
|
||||
{
|
||||
uintptr_t mask = -1ul;
|
||||
HANDLE_FAULT(sbi_remote_sfence_vma(&mask, -1ul, 0, mask));
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_all_local(void)
|
||||
{
|
||||
__asm__ volatile("sfence.vma" ::: "memory");
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_aspace(rt_aspace_t aspace)
|
||||
{
|
||||
// TODO ASID
|
||||
rt_hw_tlb_invalidate_all_local();
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_page(rt_aspace_t aspace, void *start)
|
||||
{
|
||||
__asm__ volatile("sfence.vma %0, zero" ::"r"(start) : "memory");
|
||||
}
|
||||
|
||||
static inline void rt_hw_tlb_invalidate_range(rt_aspace_t aspace, void *start,
|
||||
size_t size, size_t stride)
|
||||
{
|
||||
// huge page is taking as normal page
|
||||
if (size <= ARCH_PAGE_SIZE)
|
||||
{
|
||||
rt_hw_tlb_invalidate_page(aspace, start);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_tlb_invalidate_aspace(aspace);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __TLB_H__ */
|
||||
+66
-15
@@ -12,6 +12,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "encoding.h"
|
||||
#include "mm_fault.h"
|
||||
#include "stack.h"
|
||||
#include "sbi.h"
|
||||
#include "riscv.h"
|
||||
@@ -139,7 +140,17 @@ extern struct rt_irq_desc irq_desc[];
|
||||
|
||||
#include "rtdbg.h"
|
||||
#include "encoding.h"
|
||||
void sys_exit(int value);
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
static volatile int nested = 0;
|
||||
#define ENTER_TRAP \
|
||||
nested += 1
|
||||
#define EXIT_TRAP \
|
||||
nested -= 1
|
||||
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
|
||||
if (nested != 1) \
|
||||
handle_nested_trap_panic(cause, tval, epc, eframe)
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
static const char *get_exception_msg(int id)
|
||||
{
|
||||
@@ -161,10 +172,59 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
||||
rt_size_t id = __MASKVALUE(scause, __MASK(63UL));
|
||||
|
||||
/* user page fault */
|
||||
if (id == EP_LOAD_PAGE_FAULT ||
|
||||
id == EP_STORE_PAGE_FAULT)
|
||||
enum rt_mm_fault_op fault_op;
|
||||
enum rt_mm_fault_type fault_type;
|
||||
switch (id)
|
||||
{
|
||||
if (arch_expand_user_stack((void *)stval))
|
||||
case EP_LOAD_PAGE_FAULT:
|
||||
fault_op = MM_FAULT_OP_READ;
|
||||
fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
||||
break;
|
||||
case EP_LOAD_ACCESS_FAULT:
|
||||
fault_op = MM_FAULT_OP_READ;
|
||||
fault_type = MM_FAULT_TYPE_ACCESS_FAULT;
|
||||
break;
|
||||
case EP_LOAD_ADDRESS_MISALIGNED:
|
||||
fault_op = MM_FAULT_OP_READ;
|
||||
fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
||||
break;
|
||||
case EP_STORE_PAGE_FAULT:
|
||||
fault_op = MM_FAULT_OP_WRITE;
|
||||
fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
||||
break;
|
||||
case EP_STORE_ACCESS_FAULT:
|
||||
fault_op = MM_FAULT_OP_WRITE;
|
||||
fault_type = MM_FAULT_TYPE_ACCESS_FAULT;
|
||||
break;
|
||||
case EP_STORE_ADDRESS_MISALIGNED:
|
||||
fault_op = MM_FAULT_OP_WRITE;
|
||||
fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
||||
break;
|
||||
case EP_INSTRUCTION_PAGE_FAULT:
|
||||
fault_op = MM_FAULT_OP_EXECUTE;
|
||||
fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
||||
break;
|
||||
case EP_INSTRUCTION_ACCESS_FAULT:
|
||||
fault_op = MM_FAULT_OP_EXECUTE;
|
||||
fault_type = MM_FAULT_TYPE_ACCESS_FAULT;
|
||||
break;
|
||||
case EP_INSTRUCTION_ADDRESS_MISALIGNED:
|
||||
fault_op = MM_FAULT_OP_EXECUTE;
|
||||
fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
||||
break;
|
||||
default:
|
||||
fault_op = 0;
|
||||
}
|
||||
|
||||
if (fault_op)
|
||||
{
|
||||
struct rt_mm_fault_msg msg = {
|
||||
.fault_op = fault_op,
|
||||
.fault_type = fault_type,
|
||||
.vaddr = (void *)stval,
|
||||
};
|
||||
|
||||
if (rt_mm_fault_try_fix(&msg))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -176,6 +236,8 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
||||
rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
|
||||
|
||||
LOG_E("User Fault, killing thread: %s", rt_thread_self()->name);
|
||||
|
||||
EXIT_TRAP;
|
||||
sys_exit(-1);
|
||||
}
|
||||
#endif
|
||||
@@ -228,17 +290,6 @@ static void handle_nested_trap_panic(
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
static volatile int nested = 0;
|
||||
#define ENTER_TRAP \
|
||||
nested += 1
|
||||
#define EXIT_TRAP \
|
||||
nested -= 1
|
||||
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
|
||||
if (nested != 1) \
|
||||
handle_nested_trap_panic(cause, tval, epc, eframe)
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
/* Trap entry */
|
||||
void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user