[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:
Shell
2023-01-08 21:08:55 -05:00
committed by GitHub
parent 7f9ccd3c80
commit 7450ef6c4d
121 changed files with 5947 additions and 7041 deletions
+1 -26
View File
@@ -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
+1 -1
View File
@@ -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)
{
+13 -2
View File
@@ -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__*/
+10 -4
View File
@@ -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();
File diff suppressed because it is too large Load Diff
+52 -81
View File
@@ -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
+80
View File
@@ -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__ */
+45 -4
View File
@@ -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;
}
+10 -9
View File
@@ -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:
+2 -2
View File
@@ -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
+2
View File
@@ -10,6 +10,8 @@
#ifndef CPUPORT_H__
#define CPUPORT_H__
#include <rtthread.h>
/* the exception stack without VFP registers */
struct rt_hw_exp_stack
{
+4 -3
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+34 -17
View File
@@ -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
+9 -16
View File
@@ -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
+48
View File
@@ -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__ */
+19 -9
View File
@@ -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
}
+137
View File
@@ -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 */
+2 -2
View File
@@ -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
+3 -4
View File
@@ -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)
+5 -3
View File
@@ -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);
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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:
File diff suppressed because it is too large Load Diff
+67 -29
View File
@@ -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
+2 -10
View File
@@ -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);
}
+33 -12
View File
@@ -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();
+42 -43
View File
@@ -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++);
}
}
+4 -2
View File
@@ -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);
+61
View File
@@ -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__ */
+58 -19
View File
@@ -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)
;
}
+3 -4
View File
@@ -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)
+2 -2
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+52 -38
View File
@@ -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
+2 -12
View File
@@ -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);
+4 -9
View File
@@ -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
View File
@@ -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;
+3 -1
View File
@@ -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);
+24
View File
@@ -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;
}
}
+4 -2
View File
@@ -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
-1
View File
@@ -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"
+61
View File
@@ -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
View File
@@ -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)
{