Skip to content

feat: riscv64: Unify the 'c906' and 'virt64' architecture portings #9181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 11, 2024
Merged
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
8 changes: 2 additions & 6 deletions bsp/qemu-virt64-riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ rsource "driver/Kconfig"
config BOARD_QEMU_VIRT_RV64
bool
select ARCH_RISCV64
select ARCH_CONTEXT_EXTEND
select ARCH_USING_RISCV_COMMON64
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select RT_USING_CACHE
select ARCH_MM_MMU
select ARCH_REMAP_KERNEL
select RT_USING_HW_ATOMIC
default y

config ENABLE_FPU
bool "Enable FPU"
select ARCH_RISCV_FPU
default y

config ENABLE_VECTOR
bool "Using RISC-V Vector Extension"
select ARCH_RISCV_VECTOR
default n

if ENABLE_VECTOR
Expand All @@ -52,10 +52,6 @@ config RT_USING_VIRTIO_MMIO_ALIGN
bool "Open packed attribution, this may caused an error on virtio"
default n

config ARCH_USING_NEW_CTX_SWITCH
bool
default y

config __STACKSIZE__
int "stack size for interrupt"
default 4096
8 changes: 8 additions & 0 deletions libcpu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ config ARCH_RISCV
config ARCH_RISCV_FPU
bool

config ARCH_RISCV_VECTOR
bool

config ARCH_RISCV_FPU_S
select ARCH_RISCV_FPU
bool
Expand All @@ -263,10 +266,15 @@ config ARCH_RISCV64
bool

if ARCH_RISCV64
config ARCH_USING_NEW_CTX_SWITCH
bool
default y

config ARCH_USING_RISCV_COMMON64
bool
depends on ARCH_RISCV64
select RT_USING_CPUTIME
select ARCH_USING_NEW_CTX_SWITCH
help
Using the common64 implementation under ./libcpu/risc-v
endif
Expand Down
4 changes: 3 additions & 1 deletion libcpu/risc-v/t-head/c906/SConscript
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# RT-Thread building script for component

from building import *

cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
CPPPATH = [cwd]

if not GetDepend('ARCH_USING_ASID'):
SrcRemove(src, ['asid.c'])

group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH)

Return('group')
85 changes: 85 additions & 0 deletions libcpu/risc-v/t-head/c906/asid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-07-12 RT-Thread first version.
*/
#define DBG_TAG "hw.asid"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

#include <rtthread.h>
#include <board.h>
#include <cache.h>
#include <mm_aspace.h>
#include <mm_page.h>
#include <mmu.h>
#include <riscv_mmu.h>
#include <tlb.h>

static rt_uint8_t ASID_BITS = 0;
static rt_uint32_t next_asid;
static rt_uint64_t global_asid_generation;
#define ASID_MASK ((1 << ASID_BITS) - 1)
#define ASID_FIRST_GENERATION (1 << ASID_BITS)
#define MAX_ASID ASID_FIRST_GENERATION

void rt_hw_asid_init(void)
{
unsigned int satp_reg = read_csr(satp);
satp_reg |= (((rt_uint64_t)0xffff) << PPN_BITS);
write_csr(satp, satp_reg);
unsigned short valid_asid_bit = ((read_csr(satp) >> PPN_BITS) & 0xffff);

// The maximal value of ASIDLEN, is 9 for Sv32 or 16 for Sv39, Sv48, and Sv57
for (unsigned i = 0; i < 16; i++)
{
if (!(valid_asid_bit & 0x1))
{
break;
}

valid_asid_bit >>= 1;
ASID_BITS++;
}

global_asid_generation = ASID_FIRST_GENERATION;
next_asid = 1;
}

static rt_uint64_t _asid_acquire(rt_aspace_t aspace)
{
if ((aspace->asid ^ global_asid_generation) >> ASID_BITS) // not same generation
{
if (next_asid != MAX_ASID)
{
aspace->asid = global_asid_generation | next_asid;
next_asid++;
}
else
{
// scroll to next generation
global_asid_generation += ASID_FIRST_GENERATION;
next_asid = 1;
rt_hw_tlb_invalidate_all_local();

aspace->asid = global_asid_generation | next_asid;
next_asid++;
}
}

return aspace->asid & ASID_MASK;
}

void rt_hw_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl)
{
rt_uint64_t asid = _asid_acquire(aspace);
write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) |
(asid << PPN_BITS) |
((rt_ubase_t)pgtbl >> PAGE_OFFSET_BIT));
asm volatile("sfence.vma x0,%0"::"r"(asid):"memory");
}

186 changes: 88 additions & 98 deletions libcpu/risc-v/t-head/c906/backtrace.c
Original file line number Diff line number Diff line change
@@ -1,137 +1,127 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-10-18 Shell Add backtrace support
*/

#include <rtthread.h>
#ifdef RT_USING_SMART
#include <lwp_arch.h>

#define TRANCE_LEVEL 20
#define DBG_TAG "hw.backtrace"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

extern rt_ubase_t __text_start[];
extern rt_ubase_t __text_end[];
#include <rtthread.h>
#include <mm_aspace.h>
#include "riscv_mmu.h"
#include "stack.h"

static char *_get_elf_name(size_t sepc);
#define WORD sizeof(rt_base_t)
#define ARCH_CONTEXT_FETCH(pctx, id) (*(((unsigned long *)pctx) + (id)))

void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc)
rt_inline rt_err_t _bt_kaddr(rt_ubase_t *fp, struct rt_hw_backtrace_frame *frame)
{
rt_ubase_t *ra;
rt_ubase_t *fp;
rt_ubase_t vas, vae;
int i, j;
rt_err_t rc;
frame->fp = *(fp - 2);
frame->pc = *(fp - 1);

rt_kprintf("riscv64-unknown-linux-musl-addr2line -e %s -a -f", _get_elf_name(sepc));
if ((rt_ubase_t)fp == frame->fp)
{
rc = -RT_ERROR;
}
else
{
rc = RT_EOK;
}
return rc;
}

fp = (rt_ubase_t *)ffp;
#ifdef RT_USING_SMART
#include <lwp_arch.h>
#include <lwp_user_mm.h>

if (!fp)
rt_inline rt_err_t _bt_uaddr(rt_lwp_t lwp, rt_ubase_t *fp, struct rt_hw_backtrace_frame *frame)
{
rt_err_t rc;
if (lwp_data_get(lwp, &frame->fp, fp - 2, WORD) != WORD)
{
asm volatile("mv %0, s0"
: "=r"(fp));
rc = -RT_EFAULT;
}

if (sepc)
else if (lwp_data_get(lwp, &frame->pc, fp - 1, WORD) != WORD)
{
rt_kprintf(" %p", sepc - 0x4);
rc = -RT_EFAULT;
}

if (fp > (rt_ubase_t *)USER_VADDR_START && fp < (rt_ubase_t *)USER_VADDR_TOP)
else if ((rt_ubase_t)fp == frame->fp)
{
vas = USER_VADDR_START;
vae = USER_VADDR_TOP;
rc = -RT_ERROR;
}
else
{
vas = (rt_ubase_t)&__text_start;
vae = (rt_ubase_t)&__text_end;
frame->pc -= 0;
rc = RT_EOK;
}
return rc;
}
#endif /* RT_USING_SMART */

for (i = j = 0; i < TRANCE_LEVEL; i++)
rt_err_t rt_hw_backtrace_frame_unwind(rt_thread_t thread, struct rt_hw_backtrace_frame *frame)
{
rt_err_t rc = -RT_ERROR;
rt_uintptr_t *fp = (rt_uintptr_t *)frame->fp;

if (fp && !((long)fp & 0x7))
{
if (RT_ALIGN((rt_ubase_t)fp, sizeof(void *)) != (rt_ubase_t)fp)
#ifdef RT_USING_SMART
if (thread->lwp)
{
break;
void *lwp = thread->lwp;
void *this_lwp = lwp_self();
if (this_lwp == lwp && rt_hw_mmu_v2p(((rt_lwp_t)lwp)->aspace, fp) != ARCH_MAP_FAILED)
{
rc = _bt_kaddr(fp, frame);
}
else if (lwp_user_accessible_ext(lwp, (void *)fp, WORD))
{
rc = _bt_uaddr(lwp, fp, frame);
}
else
{
rc = -RT_EFAULT;
}
}
else
#endif
if ((rt_kmem_v2p(fp) != ARCH_MAP_FAILED))
{
rc = _bt_kaddr(fp, frame);
}
else
{
rc = -RT_EINVAL;
}

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;
else
{
rc = -RT_EFAULT;
}
return rc;
}
INIT_BOARD_EXPORT(rt_hw_backtrace_init);

static void backtrace_test(int args, char *argv[])
rt_err_t rt_hw_backtrace_frame_get(rt_thread_t thread, struct rt_hw_backtrace_frame *frame)
{
int *p = (void *)-1;
init_fn_t ft = 0;
rt_err_t rc;

if (args < 2)
if (!thread || !frame)
{
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();
rc = -RT_EINVAL;
}
else
{
rt_kprintf("Unknown cmd :%s.\r\n", argv[1]);
rt_hw_switch_frame_t sframe = thread->sp;
frame->pc = sframe->regs[RT_HW_SWITCH_CONTEXT_RA];
frame->fp = sframe->regs[RT_HW_SWITCH_CONTEXT_S0];;
rc = RT_EOK;
}
return rc;
}
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->parent.name : "rtthread.elf";
}

#endif /* RT_USING_SMART */
Loading
Loading