mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-07 00:59:00 +08:00
[smart][risc-v/libcpu] port rv64 cpu code (#6704)
* [risc-v/libcpu] porting Smart & RTOS * [fix] rv64 plic * [risc-v/rv64] remove macro in rtdef
This commit is contained in:
+12
-178
File diff suppressed because it is too large
Load Diff
@@ -29,10 +29,6 @@ config BOARD_QEMU_VIRT_RV64
|
||||
select ARCH_MM_MMU
|
||||
default y
|
||||
|
||||
config RT_USING_USERSPACE
|
||||
bool
|
||||
default y
|
||||
|
||||
config ENABLE_FPU
|
||||
bool "Enable FPU"
|
||||
default y
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
|
||||
#ifdef RT_USING_UTEST
|
||||
#if defined(RT_USING_UTEST) && defined(RT_USING_SMART)
|
||||
|
||||
#include "riscv_mmu.h"
|
||||
#include "mmu.h"
|
||||
|
||||
@@ -156,6 +156,7 @@ int rt_hw_uart_init(void)
|
||||
RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
|
||||
uart);
|
||||
rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, RT_CONSOLE_DEVICE_NAME);
|
||||
rt_hw_interrupt_umask(uart->irqno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -278,11 +278,6 @@
|
||||
|
||||
/* peripheral libraries and drivers */
|
||||
|
||||
/* sensors drivers */
|
||||
|
||||
|
||||
/* touch drivers */
|
||||
|
||||
|
||||
/* Kendryte SDK */
|
||||
|
||||
@@ -290,9 +285,6 @@
|
||||
/* AI packages */
|
||||
|
||||
|
||||
/* Signal Processing and Control Algorithm Packages */
|
||||
|
||||
|
||||
/* miscellaneous packages */
|
||||
|
||||
/* project laboratory */
|
||||
@@ -336,15 +328,6 @@
|
||||
|
||||
/* Uncategorized */
|
||||
|
||||
/* Privated Packages of RealThread */
|
||||
|
||||
|
||||
/* Network Utilities */
|
||||
|
||||
|
||||
/* RT-Thread Smart */
|
||||
|
||||
|
||||
/* RISC-V QEMU virt64 configs */
|
||||
|
||||
#define RISCV_S_MODE
|
||||
|
||||
@@ -38,7 +38,7 @@ if PLATFORM == 'gcc':
|
||||
OBJCPY = PREFIX + 'objcopy'
|
||||
|
||||
DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64 '
|
||||
CFLAGS = DEVICE + '-ffreestanding -flax-vector-conversions -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields'
|
||||
CFLAGS = DEVICE + '-ffreestanding -flax-vector-conversions -Wno-cpp -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields'
|
||||
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__ '
|
||||
LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,_start -T link.lds' + ' -lsupc++ -lgcc -static'
|
||||
CPATH = ''
|
||||
|
||||
@@ -50,6 +50,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
rt_mmu_info* arch_kernel_get_mmu_info(void);
|
||||
int arch_expand_user_stack(void *addr);
|
||||
|
||||
rt_inline unsigned long rt_hw_ffz(unsigned long x)
|
||||
{
|
||||
|
||||
@@ -1320,7 +1320,7 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
|
||||
#ifdef RT_USING_MUSL
|
||||
extern char **__environ;
|
||||
#else
|
||||
char __environ = 0;
|
||||
char **__environ = 0;
|
||||
#endif
|
||||
|
||||
pid_t exec(char *filename, int debug, int argc, char **argv)
|
||||
|
||||
+2
-3
@@ -155,9 +155,6 @@ typedef rt_base_t rt_off_t; /**< Type for offset */
|
||||
|
||||
/* Common Utilities */
|
||||
|
||||
#define _RT_STRINGIFY(x...) #x
|
||||
#define RT_STRINGIFY(x...) _RT_STRINGIFY(x)
|
||||
|
||||
#define RT_UNUSED(x) ((void)x)
|
||||
|
||||
/* Compiler Related Definitions */
|
||||
@@ -190,6 +187,8 @@ typedef __gnuc_va_list va_list;
|
||||
#define va_end(v) __builtin_va_end(v)
|
||||
#define va_arg(v,l) __builtin_va_arg(v,l)
|
||||
#endif /* RT_USING_LIBC */
|
||||
#define __RT_STRINGIFY(x...) #x
|
||||
#define RT_STRINGIFY(x...) __RT_STRINGIFY(x)
|
||||
#define RT_SECTION(x) __attribute__((section(x)))
|
||||
#define RT_USED __attribute__((used))
|
||||
#define ALIGN(n) __attribute__((aligned(n)))
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#ifdef RT_USING_SMART
|
||||
#include <lwp_arch.h>
|
||||
|
||||
#define TRANCE_LEVEL 20
|
||||
@@ -132,3 +134,5 @@ static char *_get_elf_name(size_t sepc)
|
||||
{
|
||||
return IN_USERSPACE ? rt_current_thread->name : "rtthread.elf";
|
||||
}
|
||||
|
||||
#endif /* RT_USING_SMART */
|
||||
|
||||
@@ -14,9 +14,8 @@
|
||||
|
||||
#include "cpuport.h"
|
||||
#include "stack.h"
|
||||
#include "sbi.h"
|
||||
|
||||
#include <lwp_arch.h>
|
||||
#include <sbi.h>
|
||||
#include <encoding.h>
|
||||
|
||||
#define K_SSTATUS_DEFAULT (SSTATUS_SPP | SSTATUS_SPIE | SSTATUS_SUM | SSTATUS_FS)
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ typedef union {
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <rtthread.h>
|
||||
rt_inline void rt_hw_dsb()
|
||||
{
|
||||
asm volatile("fence":::"memory");
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
*/
|
||||
#include <plic.h>
|
||||
#include <mmu.h>
|
||||
#include <lwp_arch.h>
|
||||
#include "tick.h"
|
||||
#include "encoding.h"
|
||||
#include "riscv.h"
|
||||
|
||||
@@ -43,10 +43,12 @@ _save_context:
|
||||
// now we are ready to enter interrupt / excepiton handler
|
||||
_distinguish_syscall:
|
||||
csrr t0, scause
|
||||
#ifdef RT_USING_SMART
|
||||
// TODO swap 8 with config macro name
|
||||
li t1, 8
|
||||
beq t0, t1, syscall_entry
|
||||
// syscall never return here
|
||||
#endif
|
||||
|
||||
_handle_interrupt_and_exception:
|
||||
mv a0, t0
|
||||
@@ -70,9 +72,11 @@ _context_switch:
|
||||
jal rt_hw_context_switch
|
||||
|
||||
_resume_execution:
|
||||
#ifdef RT_USING_SMART
|
||||
LOAD t0, FRAME_OFF_SSTATUS(sp)
|
||||
andi t0, t0, SSTATUS_SPP
|
||||
beqz t0, arch_ret_to_user
|
||||
#endif
|
||||
|
||||
_resume_kernel:
|
||||
RESTORE_ALL
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
|
||||
#include <board.h>
|
||||
#include <page.h>
|
||||
#include <stdlib.h>
|
||||
@@ -639,3 +642,5 @@ void rt_hw_mmu_setup(rt_mmu_info *mmu_info, struct mem_desc *mdesc, int desc_nr)
|
||||
|
||||
rt_hw_mmu_switch((void *)MMUTable);
|
||||
}
|
||||
|
||||
#endif /* RT_USING_SMART */
|
||||
|
||||
+49
-42
@@ -6,6 +6,7 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic first version
|
||||
* 2022-09-16 WangXiaoyao Porting to rv64
|
||||
*/
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
@@ -18,31 +19,39 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
#include <ioremap.h>
|
||||
#else
|
||||
#define rt_ioremap(addr, ...) (addr)
|
||||
#endif
|
||||
|
||||
size_t plic_base = 0x0c000000L;
|
||||
|
||||
/*
|
||||
* Each PLIC interrupt source can be assigned a priority by writing
|
||||
* to its 32-bit memory-mapped priority register.
|
||||
* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority.
|
||||
* A priority value of 0 is reserved to mean "never interrupt" and
|
||||
* effectively disables the interrupt.
|
||||
* Priority 1 is the lowest active priority, and priority 7 is the highest.
|
||||
* Ties between global interrupts of the same priority are broken by
|
||||
* the Interrupt ID; interrupts with the lowest ID have the highest
|
||||
* effective priority.
|
||||
*/
|
||||
* Each PLIC interrupt source can be assigned a priority by writing
|
||||
* to its 32-bit memory-mapped priority register.
|
||||
* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority.
|
||||
* A priority value of 0 is reserved to mean "never interrupt" and
|
||||
* effectively disables the interrupt.
|
||||
* Priority 1 is the lowest active priority, and priority 7 is the highest.
|
||||
* Ties between global interrupts of the same priority are broken by
|
||||
* the Interrupt ID; interrupts with the lowest ID have the highest
|
||||
* effective priority.
|
||||
*/
|
||||
void plic_set_priority(int irq, int priority)
|
||||
{
|
||||
*(uint32_t*)PLIC_PRIORITY(irq) = priority;
|
||||
*(uint32_t *)PLIC_PRIORITY(irq) = priority;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each global interrupt can be enabled by setting the corresponding
|
||||
* bit in the enables registers.
|
||||
*/
|
||||
* Each global interrupt can be enabled by setting the corresponding
|
||||
* bit in the enables registers.
|
||||
*/
|
||||
void plic_irq_enable(int irq)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
*(uint32_t*)PLIC_ENABLE(hart) = ((*(uint32_t*)PLIC_ENABLE(hart)) | (1 << irq));
|
||||
#ifdef RISCV_S_MODE
|
||||
*(uint32_t *)PLIC_ENABLE(hart) = ((*(uint32_t *)PLIC_ENABLE(hart)) | (1 << irq));
|
||||
#ifdef RISCV_S_MODE
|
||||
set_csr(sie, read_csr(sie) | MIP_SEIP);
|
||||
#else
|
||||
set_csr(mie, read_csr(mie) | MIP_MEIP);
|
||||
@@ -52,20 +61,20 @@ void plic_irq_enable(int irq)
|
||||
void plic_irq_disable(int irq)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
*(uint32_t*)PLIC_ENABLE(hart) = (((*(uint32_t*)PLIC_ENABLE(hart)) & (~(1 << irq))));
|
||||
*(uint32_t *)PLIC_ENABLE(hart) = (((*(uint32_t *)PLIC_ENABLE(hart)) & (~(1 << irq))));
|
||||
}
|
||||
|
||||
/*
|
||||
* PLIC will mask all interrupts of a priority less than or equal to threshold.
|
||||
* Maximum threshold is 7.
|
||||
* For example, a threshold value of zero permits all interrupts with
|
||||
* non-zero priority, whereas a value of 7 masks all interrupts.
|
||||
* Notice, the threshold is global for PLIC, not for each interrupt source.
|
||||
*/
|
||||
* PLIC will mask all interrupts of a priority less than or equal to threshold.
|
||||
* Maximum threshold is 7.
|
||||
* For example, a threshold value of zero permits all interrupts with
|
||||
* non-zero priority, whereas a value of 7 masks all interrupts.
|
||||
* Notice, the threshold is global for PLIC, not for each interrupt source.
|
||||
*/
|
||||
void plic_set_threshold(int threshold)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
*(uint32_t*)PLIC_THRESHOLD(hart) = threshold;
|
||||
*(uint32_t *)PLIC_THRESHOLD(hart) = threshold;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -83,13 +92,13 @@ void plic_set_threshold(int threshold)
|
||||
int plic_claim(void)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
int irq = *(uint32_t*)PLIC_CLAIM(hart);
|
||||
int irq = *(uint32_t *)PLIC_CLAIM(hart);
|
||||
return irq;
|
||||
}
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
* Writing the interrupt ID it received from the claim (irq) to the
|
||||
* Writing the interrupt ID it received from the claim (irq) to the
|
||||
* complete register would signal the PLIC we've served this IRQ.
|
||||
* The PLIC does not check whether the completion ID is the same as the
|
||||
* last claim ID for that target. If the completion ID does not match an
|
||||
@@ -100,35 +109,33 @@ int plic_claim(void)
|
||||
void plic_complete(int irq)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
*(uint32_t*)PLIC_COMPLETE(hart) = irq;
|
||||
*(uint32_t *)PLIC_COMPLETE(hart) = irq;
|
||||
}
|
||||
|
||||
void plic_set_ie(rt_uint32_t word_index, rt_uint32_t val)
|
||||
{
|
||||
volatile void *plic_ie = (void *)(rt_size_t)(PLIC_BASE_ADDR + PLIC_ENABLE_BASE + word_index * 4);
|
||||
volatile void *plic_ie = (void *)(rt_size_t)(plic_base + PLIC_ENABLE_BASE + 0x80 + word_index * 4);
|
||||
writel(val, plic_ie);
|
||||
}
|
||||
|
||||
static void _set_sie(int hartid)
|
||||
{
|
||||
for (size_t i = hartid * WORD_CNT_BYTE; i < 32; i++)
|
||||
plic_set_ie(i, 0xffffffff);
|
||||
}
|
||||
|
||||
void plic_init()
|
||||
{
|
||||
int i;
|
||||
// PLIC takes up 64 MB space
|
||||
plic_base = (size_t)rt_ioremap((void *)plic_base, 64 * 1024 * 1024);
|
||||
|
||||
plic_set_threshold(0);
|
||||
|
||||
for(i = 0;i < 128;i++)
|
||||
for (int i = 0; i < CONFIG_IRQ_NR; i++)
|
||||
{
|
||||
plic_set_priority(i,7);
|
||||
plic_set_priority(i, 1);
|
||||
}
|
||||
|
||||
plic_set_ie(0,0xffffffff);
|
||||
plic_set_ie(1,0xffffffff);
|
||||
plic_set_ie(2,0xffffffff);
|
||||
plic_set_ie(3,0xffffffff);
|
||||
|
||||
rt_uint64_t addr;
|
||||
|
||||
for(addr = 0xC001000;addr <= 0xC1F1F80;addr += 4)
|
||||
{
|
||||
*((rt_uint32_t *)addr) = 0xffffffff;
|
||||
}
|
||||
// in a single core system, only current context was set
|
||||
_set_sie(__raw_hartid());
|
||||
}
|
||||
|
||||
+12
-12
@@ -15,20 +15,14 @@
|
||||
#include <rtconfig.h>
|
||||
#include <rthw.h>
|
||||
|
||||
/*
|
||||
* This machine puts platform-level interrupt controller (PLIC) here.
|
||||
* Here only list PLIC registers in Machine mode.
|
||||
*
|
||||
*/
|
||||
#define PLIC_PRIORITY_BASE 0x0
|
||||
#define PLIC_PENDING_BASE 0x1000
|
||||
#define PLIC_ENABLE_BASE 0x2000
|
||||
#define PLIC_CONTEXT_BASE 0x200000
|
||||
|
||||
#define PLIC_PRIORITY_BASE 0x0
|
||||
#define PLIC_PENDING_BASE 0x1000
|
||||
#define PLIC_ENABLE_BASE 0x2000
|
||||
#define PLIC_CONTEXT_BASE 0x200000
|
||||
extern size_t plic_base;
|
||||
|
||||
#define PLIC_BASE_ADDR 0xC000000
|
||||
|
||||
#define VIRT_PLIC_BASE 0x0c000000L
|
||||
#define VIRT_PLIC_BASE (plic_base)
|
||||
|
||||
#define PLIC_PRIORITY_OFFSET (0x0)
|
||||
#define PLIC_PENDING_OFFSET (0x1000)
|
||||
@@ -62,6 +56,12 @@
|
||||
#define PLIC_PRIORITY(id) (VIRT_PLIC_BASE + PLIC_PRIORITY_OFFSET + (id) * 4)
|
||||
#define PLIC_PENDING(id) (VIRT_PLIC_BASE + PLIC_PENDING_OFFSET + ((id) / 32))
|
||||
|
||||
#define WORD_CNT_BYTE (1024 / 8)
|
||||
|
||||
/* IRQ config in system, max 1024 (from 0 to 1023) */
|
||||
#define CONFIG_IRQ_NR (128)
|
||||
#define CONFIG_IRQ_WORD (CONFIG_IRQ_NR / 32)
|
||||
|
||||
void plic_set_priority(int irq, int priority);
|
||||
void plic_irq_enable(int irq);
|
||||
void plic_irq_disable(int irq);
|
||||
|
||||
@@ -71,8 +71,8 @@ sbi_get_impl_version(void)
|
||||
|
||||
void sbi_print_version(void)
|
||||
{
|
||||
u_int major;
|
||||
u_int minor;
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
|
||||
/* For legacy SBI implementations. */
|
||||
if (sbi_spec_version == 0)
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#ifndef _MACHINE_SBI_H_
|
||||
#define _MACHINE_SBI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <rtdef.h>
|
||||
|
||||
/* SBI Specification Version */
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
|
||||
#define DBG_TAG "syscall"
|
||||
#define DBG_LVL DBG_WARNING
|
||||
#include <rtdbg.h>
|
||||
@@ -58,3 +60,4 @@ void syscall_handler(struct rt_hw_stack_frame *regs)
|
||||
regs->epc += 4; // skip ecall instruction
|
||||
LOG_I("[0x%lx] %s ret: 0x%lx", rt_thread_self(), syscall_name, regs->a0);
|
||||
}
|
||||
#endif /* RT_USING_SMART */
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-12-08 RT-Thread first version
|
||||
*/
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "encoding.h"
|
||||
#include "stack.h"
|
||||
@@ -15,7 +17,13 @@
|
||||
#include "riscv.h"
|
||||
#include "tick.h"
|
||||
#include "plic.h"
|
||||
#include "lwp_arch.h"
|
||||
#include "riscv_mmu.h"
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
#include <lwp_arch.h>
|
||||
#else
|
||||
#define rt_hw_backtrace(...) (0)
|
||||
#endif
|
||||
|
||||
void dump_regs(struct rt_hw_stack_frame *regs)
|
||||
{
|
||||
@@ -147,11 +155,11 @@ static const char *get_exception_msg(int id)
|
||||
return msg;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
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)
|
||||
@@ -161,7 +169,6 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LOG_E("[FATAL ERROR] Exception %ld:%s\n", id, get_exception_msg(id));
|
||||
LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
||||
dump_regs(sp);
|
||||
@@ -171,6 +178,7 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
||||
LOG_E("User Fault, killing thread: %s", rt_thread_self()->name);
|
||||
sys_exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vector_enable(struct rt_hw_stack_frame *sp)
|
||||
{
|
||||
@@ -282,12 +290,14 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
||||
goto _exit;
|
||||
}
|
||||
#endif /* ENABLE_VECTOR */
|
||||
#ifdef RT_USING_SMART
|
||||
if (!(sp->sstatus & 0x100))
|
||||
{
|
||||
handle_user(scause, stval, sepc, sp);
|
||||
// if handle_user() return here, jump to u mode then
|
||||
goto _exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
// handle kernel exception:
|
||||
rt_kprintf("Unhandled Exception %ld:%s\n", id, get_exception_msg(id));
|
||||
|
||||
Reference in New Issue
Block a user