[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:
Shell
2022-12-10 22:16:42 +08:00
committed by GitHub
parent 190eda6ab0
commit e991be9c51
21 changed files with 115 additions and 268 deletions
File diff suppressed because it is too large Load Diff
-4
View File
@@ -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"
+1
View File
@@ -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;
}
-17
View File
@@ -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
+1 -1
View File
@@ -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)
{
+1 -1
View File
@@ -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
View File
@@ -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)))
+4
View File
@@ -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 */
+2 -3
View File
@@ -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)
+1
View File
@@ -60,6 +60,7 @@ typedef union {
#endif
#ifndef __ASSEMBLY__
#include <rtthread.h>
rt_inline void rt_hw_dsb()
{
asm volatile("fence":::"memory");
-1
View File
@@ -10,7 +10,6 @@
*/
#include <plic.h>
#include <mmu.h>
#include <lwp_arch.h>
#include "tick.h"
#include "encoding.h"
#include "riscv.h"
+4
View File
@@ -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
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+2 -2
View File
@@ -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)
+1
View File
@@ -48,6 +48,7 @@
#ifndef _MACHINE_SBI_H_
#define _MACHINE_SBI_H_
#include <stdint.h>
#include <rtdef.h>
/* SBI Specification Version */
+3
View File
@@ -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 */
+13 -3
View File
@@ -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));