Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions libcpu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,10 @@ config ARCH_RISCV64
select ARCH_CPU_64BIT
bool

config ARCH_RISCV_XUANTIE
select ARCH_RISCV
bool

if ARCH_RISCV
orsource "./risc-v/Kconfig"
endif
Expand All @@ -304,6 +308,14 @@ if ARCH_RISCV64
select ARCH_USING_NEW_CTX_SWITCH
help
Using the common64 implementation under ./libcpu/risc-v

if RT_USING_SMART
config CONFIG_XUANTIE_SVPBMT
int
depends on ARCH_RISCV_XUANTIE
default 1
endif

endif

config ARCH_REMAP_KERNEL
Expand Down
31 changes: 28 additions & 3 deletions libcpu/risc-v/common/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ static int mmu_map_early(rt_ubase_t *tbl, rt_uint8_t max_level,
rt_ubase_t va, rt_ubase_t pa, rt_ubase_t attr, rt_bool_t flush)
{
rt_ubase_t page, *table, off, level_shift;
rt_ubase_t pv_off = flush ? rt_kmem_pvoff() : 0;

attr = mmu_attr_fixup(attr);

Expand Down Expand Up @@ -168,7 +169,7 @@ static int mmu_map_early(rt_ubase_t *tbl, rt_uint8_t max_level,
return MMU_MAP_ERROR_NOPAGE;
}

rt_memset((void *)page, 0, ARCH_PAGE_SIZE);
rt_memset((void *)(page - pv_off), 0, ARCH_PAGE_SIZE);
table[off] = ((page >> ARCH_PAGE_SHIFT) << PTE_BITS) | PTE_V;

if (flush)
Expand All @@ -185,7 +186,7 @@ static int mmu_map_early(rt_ubase_t *tbl, rt_uint8_t max_level,

/* Step into the next level page table */
page = (table[off] >> PTE_BITS) << ARCH_PAGE_SHIFT;
table = (rt_ubase_t *)page;
table = (rt_ubase_t *)(page - pv_off);

level_shift -= VPN_BITS;
}
Expand Down Expand Up @@ -934,6 +935,12 @@ int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size,
#if __riscv_xlen == 32 && !defined(RT_USING_SMART)
/* The RV32 ioremap and MPR regions are placed below the kernel image. */
aspace_start = (rt_ubase_t)v_address - rt_mpr_size;
#elif defined(RT_USING_SMART)
/* The runtime-sized MPR can extend below the linked kernel base. */
if ((rt_ubase_t)v_address - rt_mpr_size < aspace_start)
{
aspace_start = (rt_ubase_t)v_address - rt_mpr_size;
}
#endif

rt_aspace_init(aspace, (void *)aspace_start, 0UL - aspace_start, vtable);
Expand Down Expand Up @@ -1395,10 +1402,28 @@ void *rt_hw_mmu_pgtbl_create(void)
(void *)rt_kernel_space.page_table + i * ARCH_PAGE_SIZE,
ARCH_PAGE_SIZE);
}
#else
rt_memcpy(mmu_table, rt_kernel_space.page_table, ARCH_PAGE_SIZE);
#endif

#ifdef RT_USING_SMART
/* Do not share early identity mappings with the user address space. */
rt_size_t user_start = get_top_vpn(USER_VADDR_START, satp_level_4k);
rt_size_t user_end = get_top_vpn(USER_VADDR_TOP - 1, satp_level_4k);

for (int i = 0; i < (1UL << alloc_bits); ++i)
{
rt_ubase_t *table = (void *)mmu_table + i * ARCH_PAGE_SIZE;

rt_memset(table + user_start, 0,
(user_end - user_start + 1) * sizeof(*table));
}
#endif

#ifdef MMU_PERCPU
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table,
RT_CPUS_NR * ARCH_PAGE_SIZE);
#else
rt_memcpy(mmu_table, rt_kernel_space.page_table, ARCH_PAGE_SIZE);
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE);
#endif

Expand Down
22 changes: 19 additions & 3 deletions libcpu/risc-v/common/trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
extern long list_thread(void);
#endif

void rt_hw_show_register(struct rt_hw_stack_frame *regs);

#ifdef RT_USING_LWP
#include <mm_aspace.h>
#include <lwp.h>
Expand All @@ -46,10 +48,14 @@ static void _check_fault(struct rt_hw_stack_frame *regs, uint32_t pc_adj, char *
{
rt_thread_t th;
rt_bool_t is_user_fault = !(regs->xstatus & SR_PP);
rt_base_t saved_stat = 0;

if (is_user_fault)
{
/* User backtrace and process teardown can acquire sleeping locks. */
saved_stat = csr_read_set(CSR_STATUS, SR_IE);
rt_kprintf("%s! pc = %p\n", info, regs->epc - pc_adj);
rt_hw_show_register(regs);
}

/* User stack backtrace */
Expand All @@ -65,6 +71,8 @@ static void _check_fault(struct rt_hw_stack_frame *regs, uint32_t pc_adj, char *
lwp_core_dump(regs, pc_adj);
#endif
sys_exit_group(-1);
/* Only reached when there is no LWP to terminate */
csr_write(CSR_STATUS, saved_stat);
Comment on lines 73 to +75

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

熊老师好呀!sys_exit_group(-1) 后面的 csr_write 按理走不到,IE 会一直开着。是不是先恢复再调更稳?如有误解请指正,谢谢!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是有意把恢复放在 sys_exit_group() 之后的(commit bcde514 仅补充注释说明):

  • 正常路径下 sys_exit_group() → lwp_exit() 不会返回,csr_write() 不会执行;此时保持 IE 开启是必要的:lwp_exit() 内部的 LWP_LOCK() 会调用 RT_DEBUG_SCHEDULER_AVAILABLE(1),在 UP + RT_DEBUGING_CONTEXT 下如果中断关闭会直接断言;另外进程 teardown 也可能获取 sleeping lock。
  • 只有 lwp_self() 为空、sys_exit_group() 返回 -EINVAL 时,csr_write() 才会执行并恢复进入前的 sstatus。

因此没有把恢复提前,仅在 csr_write() 前加了一条注释说明该分支。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

搜噶搜噶

}
}

Expand Down Expand Up @@ -296,6 +304,7 @@ void rt_hw_trap(struct rt_hw_stack_frame *regs)
{
rt_ubase_t xcause = regs->xcause;
rt_ubase_t tval = csr_read_clear(CSR_TVAL, 0);
rt_bool_t is_user_fault = !(regs->xstatus & SR_PP);

/* IRQ */
if (xcause & CAUSE_IRQ_FLAG)
Expand Down Expand Up @@ -364,16 +373,23 @@ void rt_hw_trap(struct rt_hw_stack_frame *regs)
case EXC_INST_PAGE_FAULT:
case EXC_LOAD_PAGE_FAULT:
case EXC_STORE_PAGE_FAULT:
#ifdef RT_USING_SMART
if (!(regs->xstatus & SR_PP) ||
#ifdef RT_USING_SMART
if (is_user_fault ||
(tval >= USER_VADDR_START && tval < USER_VADDR_TOP))
{
if (user_fault_fixable(regs, xcause, tval))
{
return;
}

/* A failed user mapping must terminate only the LWP. */
if (is_user_fault && rt_thread_self())
{
_check_fault(regs, 0, "user fault");
return;
}
}
#endif /* RT_USING_SMART */
#endif /* RT_USING_SMART */

default:
LOG_E("Unhandle Execption: (%d) %s, TVAL = %p", xcause,
Expand Down
48 changes: 46 additions & 2 deletions libcpu/risc-v/common64/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

#include <rtthread.h>
#include <rthw.h>
#include <stddef.h>
#include <stdint.h>

Expand Down Expand Up @@ -85,6 +86,20 @@ void rt_hw_aspace_switch(rt_aspace_t aspace)
uint32_t hartid = rt_hw_cpu_id();
uintptr_t ptr = (uintptr_t)aspace->page_table + (uintptr_t)(hartid * ARCH_PAGE_SIZE);
uintptr_t page_table = (uintptr_t)rt_kmem_v2p((void *)ptr);

if (page_table == (uintptr_t)ARCH_MAP_FAILED)
{
/*
* During early K230 bring-up the kernel still runs with low physical
* pointers after relocation, including MMUTable. The formal kernel
* aspace does not translate that low pointer yet, but SATP needs the
* physical page-table address, so use the low address directly.
*/
if (ptr < KERNEL_VADDR_START)
{
page_table = ptr;
}
}
#ifndef RT_USING_SMP
current_mmu_table = aspace->page_table;
#else
Expand Down Expand Up @@ -632,14 +647,14 @@ static inline void _init_region(void *vaddr, size_t size)
{
rt_ioremap_start = vaddr;
rt_ioremap_size = size;
rt_mpr_start = rt_ioremap_start - rt_mpr_size;
rt_mpr_start = (void *)((rt_ubase_t)rt_ioremap_start - rt_mpr_size);
LOG_D("rt_ioremap_start: %p, rt_mpr_start: %p", rt_ioremap_start,
rt_mpr_start);
}
#else
static inline void _init_region(void *vaddr, size_t size)
{
rt_mpr_start = vaddr - rt_mpr_size;
rt_mpr_start = (void *)((rt_ubase_t)vaddr - rt_mpr_size);
}
#endif

Expand Down Expand Up @@ -1057,6 +1072,9 @@ void rt_hw_mem_setup_early(void *pgtbl, rt_uint64_t hartid)
vs += EARLY_MAP_PAGE_SIZE_2M;
}
#endif
/* flush page table entries from data cache before enabling MMU */
rt_hw_cpu_dcache_clean(early_pgtbl, ARCH_PAGE_SIZE);

/* apply new mapping */
asm volatile("sfence.vma x0, x0");
write_csr(satp, SATP_BASE | ((size_t)early_pgtbl >> PAGE_OFFSET_BIT));
Expand All @@ -1078,6 +1096,24 @@ rt_inline int _pgtbl_order(void)
return order;
}

#ifdef RT_USING_SMART
/*
* Early identity mappings may overlap the user address range. Clear those
* entries so they are not inherited by a user address space.
*/
static void _clear_user_pgtbl_entries(rt_ubase_t *table)
{
int i;
int start_idx = USER_VADDR_START >> VPN2_SHIFT;
int end_idx = (USER_VADDR_TOP - 1) >> VPN2_SHIFT;

for (i = start_idx; i <= end_idx; i++)
{
table[i] = 0;
}
}
#endif /* RT_USING_SMART */

/**
* @brief Creates and initializes a new MMU page table.
*
Expand Down Expand Up @@ -1111,6 +1147,9 @@ void *rt_hw_mmu_pgtbl_create(void)
rt_ubase_t *dst = (rt_ubase_t *)((rt_ubase_t)mmu_table +
(rt_ubase_t)(h * ARCH_PAGE_SIZE));
rt_memcpy(dst, src, ARCH_PAGE_SIZE);
#ifdef RT_USING_SMART
_clear_user_pgtbl_entries(dst);
#endif
}
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table,
(rt_ubase_t)(1 << order) * ARCH_PAGE_SIZE);
Expand All @@ -1121,6 +1160,11 @@ void *rt_hw_mmu_pgtbl_create(void)
return RT_NULL;
}
rt_memcpy(mmu_table, rt_kernel_space.page_table, ARCH_PAGE_SIZE);

#ifdef RT_USING_SMART
_clear_user_pgtbl_entries(mmu_table);
#endif

rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE);
#endif

Expand Down
Loading