summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2021-05-21 06:41:20 +0800
committerGitHub <[email protected]>2021-05-21 06:41:20 +0800
commit9317ee2cb283bc53f75d57bbc011e34590c67427 (patch)
tree24cfad56333f871aefed4e9bc7c0f224575ae797 /libcpu
parent5ba96109c60c4b1a66ffcc39a42de2fc28fcd75e (diff)
parent5d333029924d2b467b3d5da24851132771a473b7 (diff)
Merge pull request #4705 from lizhirui/master
add qemu-riscv-virt64 bsp
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/risc-v/SConscript2
-rw-r--r--libcpu/risc-v/virt64/SConscript14
-rw-r--r--libcpu/risc-v/virt64/context_gcc.S52
-rw-r--r--libcpu/risc-v/virt64/cpuport.c120
-rw-r--r--libcpu/risc-v/virt64/cpuport.h28
-rw-r--r--libcpu/risc-v/virt64/interrupt_gcc.S101
-rw-r--r--libcpu/risc-v/virt64/riscv.h29
-rw-r--r--libcpu/risc-v/virt64/riscv_io.h109
-rw-r--r--libcpu/risc-v/virt64/stack.h52
-rw-r--r--libcpu/risc-v/virt64/stackframe.h163
-rw-r--r--libcpu/risc-v/virt64/startup_gcc.S80
-rw-r--r--libcpu/risc-v/virt64/tick.c59
-rw-r--r--libcpu/risc-v/virt64/tick.h17
13 files changed, 826 insertions, 0 deletions
diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript
index dece8b0423..18b4c2005d 100644
--- a/libcpu/risc-v/SConscript
+++ b/libcpu/risc-v/SConscript
@@ -14,6 +14,8 @@ if rtconfig.CPU == "e906" :
group = group
elif rtconfig.CPU == "nuclei" :
group = group
+elif rtconfig.CPU == "virt64" :
+ group = group
else :
group = group + SConscript(os.path.join(cwd, 'common', 'SConscript'))
diff --git a/libcpu/risc-v/virt64/SConscript b/libcpu/risc-v/virt64/SConscript
new file mode 100644
index 0000000000..b0ae20ba02
--- /dev/null
+++ b/libcpu/risc-v/virt64/SConscript
@@ -0,0 +1,14 @@
+# RT-Thread building script for component
+
+from building import *
+
+Import('rtconfig')
+
+cwd = GetCurrentDir()
+src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
+CPPPATH = [cwd]
+ASFLAGS = ''
+
+group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
+
+Return('group')
diff --git a/libcpu/risc-v/virt64/context_gcc.S b/libcpu/risc-v/virt64/context_gcc.S
new file mode 100644
index 0000000000..881bcd162c
--- /dev/null
+++ b/libcpu/risc-v/virt64/context_gcc.S
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/28 Bernard The unify RISC-V porting implementation
+ * 2018/12/27 Jesven Add SMP support
+ * 2021/02/02 lizhirui Add userspace support
+ */
+
+#include "cpuport.h"
+#include "stackframe.h"
+
+ .globl rt_hw_context_switch_to
+rt_hw_context_switch_to:
+ LOAD sp, (a0)
+
+ la s0, rt_current_thread
+ LOAD s1, (s0)
+
+ RESTORE_ALL
+ sret
+
+/*
+ * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
+ *
+ * a0 --> from
+ * a1 --> to
+ */
+ .globl rt_hw_context_switch
+rt_hw_context_switch:
+ mv t2, sp
+ li t0, 0x120//set SPIE and SPP = 1
+ csrs sstatus, t0//if enter here,caller must be in system thread
+ csrw sepc, ra//return address
+ //saved from thread context
+ SAVE_ALL
+
+ STORE t2, 32 * REGBYTES(sp)//save user_sp
+
+ STORE sp, (a0)
+
+ //restore to thread context
+ LOAD sp, (a1)
+
+ la s0, rt_current_thread
+ LOAD s1, (s0)
+
+ RESTORE_ALL
+ sret
diff --git a/libcpu/risc-v/virt64/cpuport.c b/libcpu/risc-v/virt64/cpuport.c
new file mode 100644
index 0000000000..50929125ac
--- /dev/null
+++ b/libcpu/risc-v/virt64/cpuport.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/28 Bernard The unify RISC-V porting code.
+ * 2021-02-11 lizhirui add gp support
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "cpuport.h"
+#include "stack.h"
+
+
+/**
+ * @brief from thread used interrupt context switch
+ *
+ */
+volatile rt_ubase_t rt_interrupt_from_thread = 0;
+/**
+ * @brief to thread used interrupt context switch
+ *
+ */
+volatile rt_ubase_t rt_interrupt_to_thread = 0;
+/**
+ * @brief flag to indicate context switch in interrupt or not
+ *
+ */
+volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
+
+
+/**
+ * This function will initialize thread stack
+ *
+ * @param tentry the entry of thread
+ * @param parameter the parameter of entry
+ * @param stack_addr the beginning stack address
+ * @param texit the function will be called when thread exit
+ *
+ * @return stack address
+ */
+rt_uint8_t *rt_hw_stack_init(void *tentry,
+ void *parameter,
+ rt_uint8_t *stack_addr,
+ void *texit)
+{
+ struct rt_hw_stack_frame *frame;
+ rt_uint8_t *stk;
+ int i;
+ extern int __global_pointer$;
+
+ stk = stack_addr + sizeof(rt_ubase_t);
+ stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
+ stk -= sizeof(struct rt_hw_stack_frame);
+
+ frame = (struct rt_hw_stack_frame *)stk;
+
+ for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
+ {
+ ((rt_ubase_t *)frame)[i] = 0xdeadbeef;
+ }
+
+ frame->ra = (rt_ubase_t)texit;
+ frame->gp = (rt_ubase_t)&__global_pointer$;
+ frame->a0 = (rt_ubase_t)parameter;
+ frame->epc = (rt_ubase_t)tentry;
+ frame->user_sp_exc_stack = (rt_ubase_t)(((rt_ubase_t)stk) + sizeof(struct rt_hw_stack_frame));
+
+ /* force to supervisor mode(SPP=1) and set SPIE and SUM to 1 */
+ frame->sstatus = 0x00040120;
+
+ return stk;
+}
+
+/*
+ * #ifdef RT_USING_SMP
+ * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
+ * #else
+ * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
+ * #endif
+ */
+#ifndef RT_USING_SMP
+void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
+{
+ if (rt_thread_switch_interrupt_flag == 0)
+ rt_interrupt_from_thread = from;
+
+ rt_interrupt_to_thread = to;
+ rt_thread_switch_interrupt_flag = 1;
+
+ return ;
+}
+#endif /* end of RT_USING_SMP */
+
+/** shutdown CPU */
+void rt_hw_cpu_shutdown()
+{
+ rt_uint32_t level;
+ rt_kprintf("shutdown...\n");
+
+ level = rt_hw_interrupt_disable();
+ while (level)
+ {
+ RT_ASSERT(0);
+ }
+}
+
+rt_thread_t rt_thread_sp_to_thread(void *spmember_addr)
+{
+ return (rt_thread_t)(((rt_ubase_t)spmember_addr) - (offsetof(struct rt_thread,sp)));
+}
+
+void *get_thread_kernel_stack_top(rt_thread_t thread)
+{
+ return (void *)(((rt_size_t)thread -> stack_addr) + ((rt_size_t)thread -> stack_size));
+}
diff --git a/libcpu/risc-v/virt64/cpuport.h b/libcpu/risc-v/virt64/cpuport.h
new file mode 100644
index 0000000000..bb838def4a
--- /dev/null
+++ b/libcpu/risc-v/virt64/cpuport.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018-10-03 Bernard The first version
+ */
+
+#ifndef CPUPORT_H__
+#define CPUPORT_H__
+
+#include <rtconfig.h>
+
+/* bytes of register width */
+#ifdef ARCH_CPU_64BIT
+#define STORE sd
+#define LOAD ld
+#define REGBYTES 8
+#else
+// error here, not portable
+#endif
+
+#endif
+#ifdef RISCV_U_MODE
+#define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL
+#endif \ No newline at end of file
diff --git a/libcpu/risc-v/virt64/interrupt_gcc.S b/libcpu/risc-v/virt64/interrupt_gcc.S
new file mode 100644
index 0000000000..338413866e
--- /dev/null
+++ b/libcpu/risc-v/virt64/interrupt_gcc.S
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/02 Bernard The first version
+ * 2018/12/27 Jesven Add SMP schedule
+ * 2021/02/02 lizhirui Add userspace support
+ */
+
+#include "cpuport.h"
+#include "encoding.h"
+#include "stackframe.h"
+
+ .section .text.entry
+ .align 2
+ .global trap_entry
+ .extern __stack_cpu0
+ .extern get_current_thread_kernel_stack_top
+trap_entry:
+ //backup sp
+ csrrw sp, sscratch, sp
+ //load interrupt stack
+ la sp, __stack_cpu0
+ //backup context
+ SAVE_ALL
+
+ RESTORE_SYS_GP
+
+ csrr a0, scause
+ csrrc a1, stval, zero
+ csrr a2, sepc
+ mv a3, sp
+
+ /* scause, stval, sepc, sp */
+ call handle_trap
+
+ /* need to switch new thread */
+ la s0, rt_thread_switch_interrupt_flag
+ lw s2, 0(s0)
+ beqz s2, spurious_interrupt
+ sw zero, 0(s0)
+
+.global rt_hw_context_switch_interrupt_do
+rt_hw_context_switch_interrupt_do:
+
+//switch to thread kernel stack
+ csrr t0, sstatus
+ andi t0, t0, 0x100
+ beqz t0, __restore_sp_from_tcb_interrupt
+
+__restore_sp_from_sscratch_interrupt:
+ csrr t0, sscratch
+ j __move_stack_context_interrupt
+
+__restore_sp_from_tcb_interrupt:
+ la s0, rt_interrupt_from_thread
+ LOAD a0, 0(s0)
+ jal rt_thread_sp_to_thread
+ jal get_thread_kernel_stack_top
+ mv t0, a0
+
+__move_stack_context_interrupt:
+ mv t1, sp//src
+ mv sp, t0//switch stack
+ addi sp, sp, -33 * REGBYTES
+ //copy context
+ li s0, 33//cnt
+ mv t2, sp//dst
+
+copy_context_loop_interrupt:
+ LOAD t0, 0(t1)
+ STORE t0, 0(t2)
+ addi s0, s0, -1
+ addi t1, t1, 8
+ addi t2, t2, 8
+ bnez s0, copy_context_loop_interrupt
+
+ la s0, rt_interrupt_from_thread
+ LOAD s1, 0(s0)
+ STORE sp, 0(s1)
+
+ la s0, rt_interrupt_to_thread
+ LOAD s1, 0(s0)
+ LOAD sp, 0(s1)
+
+spurious_interrupt:
+ RESTORE_ALL
+ sret
+
+.global rt_hw_interrupt_enable
+rt_hw_interrupt_enable:
+ csrs sstatus, a0
+ jr ra
+
+.global rt_hw_interrupt_disable
+rt_hw_interrupt_disable:
+ csrrci a0, sstatus, 2
+ jr ra
diff --git a/libcpu/risc-v/virt64/riscv.h b/libcpu/risc-v/virt64/riscv.h
new file mode 100644
index 0000000000..04ac4fea74
--- /dev/null
+++ b/libcpu/risc-v/virt64/riscv.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-01-30 lizhirui first version
+ */
+
+#ifndef __RISCV_H__
+#define __RISCV_H__
+
+#include <encoding.h>
+
+#define __SIZE(bit) (1UL << (bit))
+#define __MASK(bit) (__SIZE(bit) - 1UL)
+#define __UMASK(bit) (~(__MASK(bit)))
+#define __MASKVALUE(value,maskvalue) ((value) & (maskvalue))
+#define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue)))
+#define __CHECKUPBOUND(value,bit_count) (!(((rt_size_t)value) & (~__MASK(bit_count))))
+#define __CHECKALIGN(value,start_bit) (!(((rt_size_t)value) & (__MASK(start_bit))))
+
+#define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length))
+
+#define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit))
+#define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit))
+
+#endif \ No newline at end of file
diff --git a/libcpu/risc-v/virt64/riscv_io.h b/libcpu/risc-v/virt64/riscv_io.h
new file mode 100644
index 0000000000..8363ff23f8
--- /dev/null
+++ b/libcpu/risc-v/virt64/riscv_io.h
@@ -0,0 +1,109 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ * Anup Patel <[email protected]>
+ */
+
+#ifndef __RISCV_IO_H__
+#define __RISCV_IO_H__
+
+ static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
+ {
+ asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr));
+ }
+
+ static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
+ {
+ asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr));
+ }
+
+ static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
+ {
+ asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr));
+ }
+
+ #if __riscv_xlen != 32
+ static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
+ {
+ asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
+ }
+ #endif
+
+ static inline rt_uint8_t __raw_readb(const volatile void *addr)
+ {
+ rt_uint8_t val;
+
+ asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr));
+ return val;
+ }
+
+ static inline rt_uint16_t __raw_readw(const volatile void *addr)
+ {
+ rt_uint16_t val;
+
+ asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr));
+ return val;
+ }
+
+ static inline rt_uint32_t __raw_readl(const volatile void *addr)
+ {
+ rt_uint32_t val;
+
+ asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr));
+ return val;
+ }
+
+ #if __riscv_xlen != 32
+ static inline rt_uint64_t __raw_readq(const volatile void *addr)
+ {
+ rt_uint64_t val;
+
+ asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr));
+ return val;
+ }
+ #endif
+
+ /* FIXME: These are now the same as asm-generic */
+
+ /* clang-format off */
+
+ #define __io_rbr() do {} while (0)
+ #define __io_rar() do {} while (0)
+ #define __io_rbw() do {} while (0)
+ #define __io_raw() do {} while (0)
+
+ #define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
+ #define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; })
+ #define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; })
+
+ #define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); })
+ #define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); })
+ #define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
+
+ #if __riscv_xlen != 32
+ #define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; })
+ #define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); })
+ #endif
+
+ #define __io_br() do {} while (0)
+ #define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory");
+ #define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory");
+ #define __io_aw() do {} while (0)
+
+ #define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
+ #define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; })
+ #define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
+
+ #define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); })
+ #define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); })
+ #define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); })
+
+ #if __riscv_xlen != 32
+ #define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; })
+ #define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); })
+ #endif
+
+#endif \ No newline at end of file
diff --git a/libcpu/risc-v/virt64/stack.h b/libcpu/risc-v/virt64/stack.h
new file mode 100644
index 0000000000..27e9cdf9fa
--- /dev/null
+++ b/libcpu/risc-v/virt64/stack.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-01-30 lizhirui first version
+ */
+
+#ifndef __STACK_H__
+#define __STACK_H__
+
+#include <rtthread.h>
+struct rt_hw_stack_frame
+{
+ rt_ubase_t epc; /* epc - epc - program counter */
+ rt_ubase_t ra; /* x1 - ra - return address for jumps */
+ rt_ubase_t sstatus; /* - supervisor status register */
+ rt_ubase_t gp; /* x3 - gp - global pointer */
+ rt_ubase_t tp; /* x4 - tp - thread pointer */
+ rt_ubase_t t0; /* x5 - t0 - temporary register 0 */
+ rt_ubase_t t1; /* x6 - t1 - temporary register 1 */
+ rt_ubase_t t2; /* x7 - t2 - temporary register 2 */
+ rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */
+ rt_ubase_t s1; /* x9 - s1 - saved register 1 */
+ rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */
+ rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */
+ rt_ubase_t a2; /* x12 - a2 - function argument 2 */
+ rt_ubase_t a3; /* x13 - a3 - function argument 3 */
+ rt_ubase_t a4; /* x14 - a4 - function argument 4 */
+ rt_ubase_t a5; /* x15 - a5 - function argument 5 */
+ rt_ubase_t a6; /* x16 - a6 - function argument 6 */
+ rt_ubase_t a7; /* x17 - s7 - function argument 7 */
+ rt_ubase_t s2; /* x18 - s2 - saved register 2 */
+ rt_ubase_t s3; /* x19 - s3 - saved register 3 */
+ rt_ubase_t s4; /* x20 - s4 - saved register 4 */
+ rt_ubase_t s5; /* x21 - s5 - saved register 5 */
+ rt_ubase_t s6; /* x22 - s6 - saved register 6 */
+ rt_ubase_t s7; /* x23 - s7 - saved register 7 */
+ rt_ubase_t s8; /* x24 - s8 - saved register 8 */
+ rt_ubase_t s9; /* x25 - s9 - saved register 9 */
+ rt_ubase_t s10; /* x26 - s10 - saved register 10 */
+ rt_ubase_t s11; /* x27 - s11 - saved register 11 */
+ rt_ubase_t t3; /* x28 - t3 - temporary register 3 */
+ rt_ubase_t t4; /* x29 - t4 - temporary register 4 */
+ rt_ubase_t t5; /* x30 - t5 - temporary register 5 */
+ rt_ubase_t t6; /* x31 - t6 - temporary register 6 */
+ rt_ubase_t user_sp_exc_stack; /* sscratch - user mode sp/exception stack */
+};
+
+#endif
diff --git a/libcpu/risc-v/virt64/stackframe.h b/libcpu/risc-v/virt64/stackframe.h
new file mode 100644
index 0000000000..e5a5271a7a
--- /dev/null
+++ b/libcpu/risc-v/virt64/stackframe.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-02-02 lizhirui first version
+ * 2021-02-11 lizhirui fixed gp save/store bug
+ */
+
+#ifndef __STACKFRAME_H__
+#define __STACKFRAME_H__
+
+#include "cpuport.h"
+
+.macro SAVE_ALL
+ addi sp, sp, -33 * REGBYTES
+
+ STORE x1, 1 * REGBYTES(sp)
+
+ csrr x1, sstatus
+ STORE x1, 2 * REGBYTES(sp)
+
+ csrr x1, sepc
+ STORE x1, 0 * REGBYTES(sp)
+
+ STORE x3, 3 * REGBYTES(sp)
+ STORE x4, 4 * REGBYTES(sp)
+ STORE x5, 5 * REGBYTES(sp)
+ STORE x6, 6 * REGBYTES(sp)
+ STORE x7, 7 * REGBYTES(sp)
+ STORE x8, 8 * REGBYTES(sp)
+ STORE x9, 9 * REGBYTES(sp)
+ STORE x10, 10 * REGBYTES(sp)
+ STORE x11, 11 * REGBYTES(sp)
+ STORE x12, 12 * REGBYTES(sp)
+ STORE x13, 13 * REGBYTES(sp)
+ STORE x14, 14 * REGBYTES(sp)
+ STORE x15, 15 * REGBYTES(sp)
+ STORE x16, 16 * REGBYTES(sp)
+ STORE x17, 17 * REGBYTES(sp)
+ STORE x18, 18 * REGBYTES(sp)
+ STORE x19, 19 * REGBYTES(sp)
+ STORE x20, 20 * REGBYTES(sp)
+ STORE x21, 21 * REGBYTES(sp)
+ STORE x22, 22 * REGBYTES(sp)
+ STORE x23, 23 * REGBYTES(sp)
+ STORE x24, 24 * REGBYTES(sp)
+ STORE x25, 25 * REGBYTES(sp)
+ STORE x26, 26 * REGBYTES(sp)
+ STORE x27, 27 * REGBYTES(sp)
+ STORE x28, 28 * REGBYTES(sp)
+ STORE x29, 29 * REGBYTES(sp)
+ STORE x30, 30 * REGBYTES(sp)
+ STORE x31, 31 * REGBYTES(sp)
+ csrr t0, sscratch
+ STORE t0, 32 * REGBYTES(sp)
+.endm
+
+.macro RESTORE_ALL_ONLY
+ /* resw ra to sepc */
+ LOAD x1, 0 * REGBYTES(sp)
+ csrw sepc, x1
+
+ LOAD x1, 2 * REGBYTES(sp)
+ csrw sstatus, x1
+
+ LOAD x1, 1 * REGBYTES(sp)
+
+ LOAD x3, 3 * REGBYTES(sp)
+ LOAD x4, 4 * REGBYTES(sp)
+ LOAD x5, 5 * REGBYTES(sp)
+ LOAD x6, 6 * REGBYTES(sp)
+ LOAD x7, 7 * REGBYTES(sp)
+ LOAD x8, 8 * REGBYTES(sp)
+ LOAD x9, 9 * REGBYTES(sp)
+ LOAD x10, 10 * REGBYTES(sp)
+ LOAD x11, 11 * REGBYTES(sp)
+ LOAD x12, 12 * REGBYTES(sp)
+ LOAD x13, 13 * REGBYTES(sp)
+ LOAD x14, 14 * REGBYTES(sp)
+ LOAD x15, 15 * REGBYTES(sp)
+ LOAD x16, 16 * REGBYTES(sp)
+ LOAD x17, 17 * REGBYTES(sp)
+ LOAD x18, 18 * REGBYTES(sp)
+ LOAD x19, 19 * REGBYTES(sp)
+ LOAD x20, 20 * REGBYTES(sp)
+ LOAD x21, 21 * REGBYTES(sp)
+ LOAD x22, 22 * REGBYTES(sp)
+ LOAD x23, 23 * REGBYTES(sp)
+ LOAD x24, 24 * REGBYTES(sp)
+ LOAD x25, 25 * REGBYTES(sp)
+ LOAD x26, 26 * REGBYTES(sp)
+ LOAD x27, 27 * REGBYTES(sp)
+ LOAD x28, 28 * REGBYTES(sp)
+ LOAD x29, 29 * REGBYTES(sp)
+ LOAD x30, 30 * REGBYTES(sp)
+ LOAD x31, 31 * REGBYTES(sp)
+
+ addi sp, sp, 33 * REGBYTES
+.endm
+
+.macro RESTORE_ALL
+ /* resw ra to sepc */
+ LOAD x1, 0 * REGBYTES(sp)
+ csrw sepc, x1
+
+ LOAD x1, 2 * REGBYTES(sp)
+ csrw sstatus, x1
+
+ LOAD x1, 1 * REGBYTES(sp)
+
+ LOAD x3, 3 * REGBYTES(sp)
+ LOAD x4, 4 * REGBYTES(sp)
+ LOAD x5, 5 * REGBYTES(sp)
+ LOAD x6, 6 * REGBYTES(sp)
+ LOAD x7, 7 * REGBYTES(sp)
+ LOAD x8, 8 * REGBYTES(sp)
+ LOAD x9, 9 * REGBYTES(sp)
+ LOAD x10, 10 * REGBYTES(sp)
+ LOAD x11, 11 * REGBYTES(sp)
+ LOAD x12, 12 * REGBYTES(sp)
+ LOAD x13, 13 * REGBYTES(sp)
+ LOAD x14, 14 * REGBYTES(sp)
+ LOAD x15, 15 * REGBYTES(sp)
+ LOAD x16, 16 * REGBYTES(sp)
+ LOAD x17, 17 * REGBYTES(sp)
+ LOAD x18, 18 * REGBYTES(sp)
+ LOAD x19, 19 * REGBYTES(sp)
+ LOAD x20, 20 * REGBYTES(sp)
+ LOAD x21, 21 * REGBYTES(sp)
+ LOAD x22, 22 * REGBYTES(sp)
+ LOAD x23, 23 * REGBYTES(sp)
+ LOAD x24, 24 * REGBYTES(sp)
+ LOAD x25, 25 * REGBYTES(sp)
+ LOAD x26, 26 * REGBYTES(sp)
+ LOAD x27, 27 * REGBYTES(sp)
+ LOAD x28, 28 * REGBYTES(sp)
+ LOAD x29, 29 * REGBYTES(sp)
+ LOAD x30, 30 * REGBYTES(sp)
+ LOAD x31, 31 * REGBYTES(sp)
+
+ //restore user sp
+ LOAD sp, 32 * REGBYTES(sp)
+.endm
+
+.macro RESTORE_SYS_GP
+ .option push
+ .option norelax
+ la gp, __global_pointer$
+ .option pop
+.endm
+
+.macro OPEN_INTERRUPT
+ csrsi sstatus, 2
+.endm
+
+.macro CLOSE_INTERRUPT
+ csrci sstatus, 2
+.endm
+
+#endif \ No newline at end of file
diff --git a/libcpu/risc-v/virt64/startup_gcc.S b/libcpu/risc-v/virt64/startup_gcc.S
new file mode 100644
index 0000000000..9b1a27be9a
--- /dev/null
+++ b/libcpu/risc-v/virt64/startup_gcc.S
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/01 Bernard The first version
+ * 2018/12/27 Jesven Add SMP support
+ * 2020/6/12 Xim Port to QEMU and remove SMP support
+ */
+
+#define SSTATUS_FS 0x00006000U /* initial state of FPU, clear to disable */
+#include <cpuport.h>
+
+ .global _start
+ .section ".start", "ax"
+_start:
+ j 1f
+ .word 0xdeadbeef
+ .align 3
+ .global g_wake_up
+ g_wake_up:
+ .dword 1
+ .dword 0
+1:
+ csrw sie, 0
+ csrw sip, 0
+ la t0, trap_entry
+ csrw stvec, t0
+
+ li x1, 0
+ li x2, 0
+ li x3, 0
+ li x4, 0
+ li x5, 0
+ li x6, 0
+ li x7, 0
+ li x8, 0
+ li x9, 0
+ li x10,0
+ li x11,0
+ li x12,0
+ li x13,0
+ li x14,0
+ li x15,0
+ li x16,0
+ li x17,0
+ li x18,0
+ li x19,0
+ li x20,0
+ li x21,0
+ li x22,0
+ li x23,0
+ li x24,0
+ li x25,0
+ li x26,0
+ li x27,0
+ li x28,0
+ li x29,0
+ li x30,0
+ li x31,0
+
+ /* set to disable FPU */
+ li t0, SSTATUS_FS
+ csrc sstatus, t0
+ li t0, 0x40000 // SUM in sstatus
+ csrs sstatus, t0
+
+.option push
+.option norelax
+ la gp, __global_pointer$
+.option pop
+
+ // removed SMP support here
+ la sp, __stack_start__
+ li t0, __STACKSIZE__
+ add sp, sp, t0
+ csrw sscratch, sp
+ j primary_cpu_entry
diff --git a/libcpu/risc-v/virt64/tick.c b/libcpu/risc-v/virt64/tick.c
new file mode 100644
index 0000000000..4f340c544f
--- /dev/null
+++ b/libcpu/risc-v/virt64/tick.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/28 Bernard The unify RISC-V porting code.
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include <encoding.h>
+#include "sbi.h"
+
+static volatile uint64_t time_elapsed = 0;
+static volatile unsigned long tick_cycles = 0;
+
+static uint64_t get_ticks()
+{
+ __asm__ __volatile__(
+ "rdtime %0"
+ : "=r"(time_elapsed));
+ return time_elapsed;
+}
+
+int tick_isr(void)
+{
+ // uint64_t core_id = current_coreid();
+ int tick_cycles = 40000;
+ // clint->mtimecmp[core_id] += tick_cycles;
+ rt_tick_increase();
+ sbi_set_timer(get_ticks() + tick_cycles);
+
+ return 0;
+}
+
+/* Sets and enable the timer interrupt */
+int rt_hw_tick_init(void)
+{
+ /* Read core id */
+ // unsigned long core_id = current_coreid();
+ unsigned long interval = 1000/RT_TICK_PER_SECOND;
+
+ /* Clear the Supervisor-Timer bit in SIE */
+ clear_csr(sie, SIP_STIP);
+
+ /* calculate the tick cycles */
+ // tick_cycles = interval * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1;
+ tick_cycles = 40000;
+ /* Set timer */
+ sbi_set_timer(get_ticks() + tick_cycles);
+
+ /* Enable the Supervisor-Timer bit in SIE */
+ set_csr(sie, SIP_STIP);
+
+ return 0;
+}
diff --git a/libcpu/risc-v/virt64/tick.h b/libcpu/risc-v/virt64/tick.h
new file mode 100644
index 0000000000..0821004263
--- /dev/null
+++ b/libcpu/risc-v/virt64/tick.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018/10/28 Bernard The unify RISC-V porting code.
+ */
+
+#ifndef TICK_H__
+#define TICK_H__
+
+int tick_isr(void);
+int rt_hw_tick_init(void);
+
+#endif