summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
authoraozima <[email protected]>2020-10-09 15:17:27 +0800
committeraozima <[email protected]>2020-10-09 15:17:27 +0800
commit05777266b9dffe30df0bef15b35b710f6de21710 (patch)
tree6453a68327fd2d7ffb3dcbf788bd5f6d8b209528 /libcpu
parent79fd12842beeee5a653ba6f4bc2f08b21be7697a (diff)
parentaeff91b2a7fc846cf3724c01c28fbd7327bd2bac (diff)
Merge remote-tracking branch 'remotes/gitee/master' into gitee_master
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/Kconfig4
-rw-r--r--libcpu/mips/common/asm.h4
-rw-r--r--libcpu/mips/common/context_gcc.S21
-rw-r--r--libcpu/mips/common/exception.c50
-rw-r--r--libcpu/mips/common/exception_gcc.S8
-rw-r--r--libcpu/mips/common/stackframe.h12
-rw-r--r--libcpu/mips/gs264/cache.c70
-rw-r--r--libcpu/mips/gs264/cache.h24
-rw-r--r--libcpu/mips/gs264/cpuinit_gcc.S8
-rw-r--r--libcpu/mips/gs264/mips_mmu.c222
-rw-r--r--libcpu/mips/gs264/mips_mmu.h99
-rw-r--r--libcpu/mips/gs264/mipscfg.c79
-rw-r--r--libcpu/mips/gs264/mmu.c819
-rw-r--r--libcpu/mips/gs264/mmu.h113
-rw-r--r--libcpu/risc-v/SConscript13
-rw-r--r--libcpu/risc-v/nuclei/cpuport.c2
-rw-r--r--libcpu/risc-v/t-head/e906/SConscript12
-rw-r--r--libcpu/risc-v/t-head/e906/context_gcc.S323
-rw-r--r--libcpu/risc-v/t-head/e906/cpuport.c170
-rw-r--r--libcpu/risc-v/t-head/e906/cpuport.h55
20 files changed, 2077 insertions, 31 deletions
diff --git a/libcpu/Kconfig b/libcpu/Kconfig
index e355664de2..ae2767dec9 100644
--- a/libcpu/Kconfig
+++ b/libcpu/Kconfig
@@ -82,6 +82,10 @@ config ARCH_MIPS
config ARCH_MIPS64
bool
+ select ARCH_CPU_64BIT
+
+config ARCH_CPU_64BIT
+ bool
config ARCH_MIPS_XBURST
bool
diff --git a/libcpu/mips/common/asm.h b/libcpu/mips/common/asm.h
index 6a5353b803..1b39eea05a 100644
--- a/libcpu/mips/common/asm.h
+++ b/libcpu/mips/common/asm.h
@@ -261,11 +261,7 @@ symbol = value
#define LONG_SRAV srav
#define LONG .word
-#ifdef ARCH_MIPS64
-#define LONGSIZE 8
-#else
#define LONGSIZE 4
-#endif
#define LONGMASK 3
#define LONGLOG 2
diff --git a/libcpu/mips/common/context_gcc.S b/libcpu/mips/common/context_gcc.S
index cdcdede39a..3fdbe374c9 100644
--- a/libcpu/mips/common/context_gcc.S
+++ b/libcpu/mips/common/context_gcc.S
@@ -1,11 +1,12 @@
/*
- * Copyright (c) 2006-2019, RT-Thread Development Team
+ * Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-12-04 Jiaxun Yang Initial version
+ * 2020-07-26 lizhirui Fixed some problems
*/
#ifndef __ASSEMBLY__
@@ -56,12 +57,12 @@ rt_hw_context_switch_interrupt:
bnez t1, _reswitch
nop
li t1, 0x01 /* set rt_thread_switch_interrupt_flag to 1 */
- sw t1, 0(t0)
+ LONG_S t1, 0(t0)
PTR_LA t0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */
- sw a0, 0(t0)
+ LONG_S a0, 0(t0)
_reswitch:
PTR_LA t0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */
- sw a1, 0(t0)
+ LONG_S a1, 0(t0)
jr ra
nop
@@ -97,24 +98,24 @@ mips_irq_handle:
* rt_hw_context_switch_interrupt_do and do not return
*/
PTR_LA k0, rt_thread_switch_interrupt_flag
- lw k1, 0(k0)
+ LONG_L k1, 0(k0)
beqz k1, spurious_interrupt
nop
- sw zero, 0(k0) /* clear flag */
+ LONG_S zero, 0(k0) /* clear flag */
nop
/*
* switch to the new thread
*/
PTR_LA k0, rt_interrupt_from_thread
- lw k1, 0(k0)
+ LONG_L k1, 0(k0)
nop
- sw sp, 0(k1) /* store sp in preempted task TCB */
+ LONG_S sp, 0(k1) /* store sp in preempted task TCB */
PTR_LA k0, rt_interrupt_to_thread
- lw k1, 0(k0)
+ LONG_L k1, 0(k0)
nop
- lw sp, 0(k1) /* get new task stack pointer */
+ LONG_L sp, 0(k1) /* get new task stack pointer */
j spurious_interrupt
nop
diff --git a/libcpu/mips/common/exception.c b/libcpu/mips/common/exception.c
index 84bb0446d6..3da8ecead6 100644
--- a/libcpu/mips/common/exception.c
+++ b/libcpu/mips/common/exception.c
@@ -24,6 +24,41 @@ rt_ubase_t rt_interrupt_from_thread;
rt_ubase_t rt_interrupt_to_thread;
rt_ubase_t rt_thread_switch_interrupt_flag;
+const char *exception_name[] = {
+ "Interrupt",
+ "(X)TLB Modify Exception",
+ "(X)TLB Read/Fetch Exception",
+ "(X)TLB Write Exception",
+ "Address Read/Fetch Exception",
+ "Address Write Exception",
+ "",
+ "",
+ "Syscall",
+ "Breakpoint",
+ "Reversed Instruction Exception",
+ "Coprocessor Unit Invalid",
+ "Overflow",
+ "Trap",
+ "FPU Exception in Vector Instruction",
+ "FPU Exception",
+ "Loongson Custom Exception",
+ "",
+ "",
+ "(X)TLB Read Denied Exception",
+ "(X)TLB Execute Denied Exception",
+ "Vector Module Disabled Exception",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Cache Error Exception",
+ ""
+ };
+
rt_base_t rt_hw_interrupt_disable(void)
{
rt_base_t status = read_c0_status();
@@ -39,7 +74,7 @@ void rt_hw_interrupt_enable(rt_base_t level)
/**
* exception handle table
*/
-#define RT_EXCEPTION_MAX 31
+#define RT_EXCEPTION_MAX 32
exception_func_t sys_exception_handlers[RT_EXCEPTION_MAX];
/**
@@ -87,10 +122,15 @@ void cache_error_handler(void)
static void unhandled_exception_handle(struct pt_regs *regs)
{
- rt_kprintf("Unknown Exception, EPC: 0x%08x, CAUSE: 0x%08x\n", read_c0_epc(),
- read_c0_cause());
- rt_kprintf("ST0: 0x%08x ", regs->cp0_status);
- rt_kprintf("ErrorPC: 0x%08x\n", read_c0_errorepc());
+ rt_kprintf("Unknown Exception, EPC: 0x%p, CAUSE: 0x%08x\n", read_c0_epc(), read_c0_cause());
+ rt_kprintf("Exception Name:%s\n",exception_name[(read_c0_cause() >> 2) & 0x1f]);
+#ifdef SOC_LS2K1000
+ rt_kprintf("ExeCode = 0x%08x,BadAddr = 0x%p\n",(read_c0_cause() >> 2) & 0x1f,mmu_tlb_get_bad_vaddr());
+#else
+ rt_kprintf("ExeCode = 0x%08x\n",(read_c0_cause() >> 2) & 0x1f);
+#endif
+ rt_kprintf("ST0: 0x%08x ",regs->cp0_status);
+ rt_kprintf("ErrorPC: 0x%p\n",read_c0_errorepc());
mips_dump_regs(regs);
rt_hw_cpu_shutdown();
}
diff --git a/libcpu/mips/common/exception_gcc.S b/libcpu/mips/common/exception_gcc.S
index 9664438ac1..c685928a84 100644
--- a/libcpu/mips/common/exception_gcc.S
+++ b/libcpu/mips/common/exception_gcc.S
@@ -1,11 +1,12 @@
/*
- * Copyright (c) 2006-2019, RT-Thread Development Team
+ * Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-12-04 Jiaxun Yang Initial version
+ * 2020-07-26 lizhirui Add xtlb exception entry
*/
#ifndef __ASSEMBLY__
#define __ASSEMBLY__
@@ -26,6 +27,11 @@ tlb_refill_exception:
b _general_exception_handler
nop
+ /* 0x080 - XTLB refill handler */
+ .org ebase_start + 0x080
+ b _general_exception_handler
+ nop
+
/* 0x100 - Cache error handler */
.org ebase_start + 0x100
j cache_error_handler
diff --git a/libcpu/mips/common/stackframe.h b/libcpu/mips/common/stackframe.h
index 258f9a994f..bb92a18c9c 100644
--- a/libcpu/mips/common/stackframe.h
+++ b/libcpu/mips/common/stackframe.h
@@ -22,7 +22,9 @@
#ifdef RT_USING_FPU
/* Ensure CU1 (FPU) is enabled */
MFC0 v1, CP0_STATUS
- ori v1, ST0_CU1
+ lui t1, %hi(ST0_CU1)
+ addiu t1, t1, %lo(ST0_CU1)
+ or v1, v1, t1
MTC0 v1, CP0_STATUS
SSNOP
cfc1 v1, fcr31
@@ -125,11 +127,13 @@
#ifdef RT_USING_FPU
/* Ensure CU1 (FPU) is enabled */
MFC0 v1, CP0_STATUS
- ori v1, ST0_CU1
+ lui t1, %hi(ST0_CU1)
+ addiu t1, t1, %lo(ST0_CU1)
+ or v1, v1, t1
MTC0 v1, CP0_STATUS
SSNOP
LONG_L v1, PT_FPU_FCSR31(sp)
- ctc1 v1, fcsr31
+ ctc1 v1, fcr31
l.d $f0, PT_FPU_R0(sp)
l.d $f2, PT_FPU_R2(sp)
l.d $f4, PT_FPU_R4(sp)
@@ -202,6 +206,8 @@
li v1, ~(ST0_CU1 | ST0_FR | ST0_IM)
and v0, v1
or v0, a0
+ li v1, (ST0_KX | ST0_SX | ST0_UX)
+ or v0, v1
mtc0 v0, CP0_STATUS
LONG_L v1, PT_EPC(sp)
MTC0 v1, CP0_EPC
diff --git a/libcpu/mips/gs264/cache.c b/libcpu/mips/gs264/cache.c
new file mode 100644
index 0000000000..54d38d0d3f
--- /dev/null
+++ b/libcpu/mips/gs264/cache.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2019-03-29 quanzhao the first version
+ * 2020-07-26 lizhirui porting to ls2k
+ */
+
+#include <rthw.h>
+#include <rtdef.h>
+
+rt_inline rt_uint64_t rt_cpu_icache_line_size(void)
+{
+ rt_uint64_t ctr;
+ return 4 << (ctr & 0xF);
+}
+
+rt_inline rt_uint64_t rt_cpu_dcache_line_size(void)
+{
+ rt_uint64_t ctr;
+ return 4 << ((ctr >> 16) & 0xF);
+}
+
+void rt_hw_cpu_icache_invalidate(void *addr, int size)
+{
+ rt_uint64_t line_size = rt_cpu_icache_line_size();
+ rt_uint64_t start_addr = (rt_uint64_t)addr;
+ rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1;
+}
+
+void rt_hw_cpu_dcache_invalidate(void *addr, int size)
+{
+ rt_uint64_t line_size = rt_cpu_dcache_line_size();
+ rt_uint64_t start_addr = (rt_uint64_t)addr;
+ rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1;
+}
+
+void rt_hw_cpu_dcache_clean(void *addr, int size)
+{
+ rt_uint64_t line_size = rt_cpu_dcache_line_size();
+ rt_uint64_t start_addr = (rt_uint64_t)addr;
+ rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1;
+}
+
+void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
+{
+ if (ops == RT_HW_CACHE_INVALIDATE)
+ rt_hw_cpu_icache_invalidate(addr, size);
+}
+
+void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
+{
+ if (ops == RT_HW_CACHE_FLUSH)
+ rt_hw_cpu_dcache_clean(addr, size);
+ else if (ops == RT_HW_CACHE_INVALIDATE)
+ rt_hw_cpu_dcache_invalidate(addr, size);
+}
+
+rt_base_t rt_hw_cpu_icache_status(void)
+{
+ return 0;
+}
+
+rt_base_t rt_hw_cpu_dcache_status(void)
+{
+ return 0;
+}
diff --git a/libcpu/mips/gs264/cache.h b/libcpu/mips/gs264/cache.h
new file mode 100644
index 0000000000..10a4afd899
--- /dev/null
+++ b/libcpu/mips/gs264/cache.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018-03-25 quanzhao the first version
+ */
+#ifndef __CACHE_H__
+#define __CACHE_H__
+
+unsigned long rt_cpu_get_smp_id(void);
+
+void rt_cpu_mmu_disable(void);
+void rt_cpu_mmu_enable(void);
+void rt_cpu_tlb_set(volatile unsigned long*);
+
+void rt_cpu_dcache_clean_flush(void);
+void rt_cpu_icache_flush(void);
+
+void rt_cpu_vector_set_base(unsigned int addr);
+
+#endif
diff --git a/libcpu/mips/gs264/cpuinit_gcc.S b/libcpu/mips/gs264/cpuinit_gcc.S
index bd84663350..592fedd88a 100644
--- a/libcpu/mips/gs264/cpuinit_gcc.S
+++ b/libcpu/mips/gs264/cpuinit_gcc.S
@@ -19,8 +19,8 @@
.globl rt_cpu_early_init
rt_cpu_early_init:
- mfc0 t0, CP0_CONFIG
- ori t0, 3
- mtc0 t0, CP0_CONFIG
+ mfc0 t0, CP0_CONFIG
+ ori t0, 3
+ mtc0 t0, CP0_CONFIG
ehb
- jr ra \ No newline at end of file
+ jr ra
diff --git a/libcpu/mips/gs264/mips_mmu.c b/libcpu/mips/gs264/mips_mmu.c
new file mode 100644
index 0000000000..7bed69596a
--- /dev/null
+++ b/libcpu/mips/gs264/mips_mmu.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-07-26 lizhirui the first version
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "mips.h"
+#include "mips_mmu.h"
+
+void mmu_init()
+{
+ uint32_t status = read_c0_status();
+ status |= 0x07 << 5;//ux = 1,sx = 1,kx = 1
+ write_c0_status(status);
+
+ mmu_clear_tlb();
+ mmu_clear_itlb();
+}
+
+void mmu_set_cpu_mode(cpu_mode_t cpu_mode)
+{
+ uint32_t status = read_c0_status();
+ status &= ~(0x03 << 3);
+ status |= ((uint32_t)cpu_mode & 0x03) << 3;
+ write_c0_status(status);
+}
+
+cpu_mode_t mmu_get_cpu_mode()
+{
+ uint32_t status = read_c0_status();
+ return (cpu_mode_t)((status >> 3) & 0x03);
+}
+
+void mmu_clear_tlb()
+{
+ uint32_t max_tlb_index = mmu_get_max_tlb_index();
+ uint64_t va = KSEG0BASE;
+ uint32_t entry;
+ tlb_item_t tlb_item;
+
+ for(entry = 0;entry <= max_tlb_index;entry++)
+ {
+ mmu_tlb_item_init(&tlb_item);
+ mmu_tlb_write_indexed(entry,&tlb_item);
+ }
+}
+
+void mmu_clear_itlb()
+{
+ uint32_t diag = read_c0_diag();
+ write_c0_diag(diag | (0x01 << 2));//write ITLB bit
+ read_c0_entrylo0();
+}
+
+uint32_t mmu_get_max_tlb_index()
+{
+ uint32_t config1 = read_c0_config1();
+ return ((config1 >> 25) & 0x3F);
+}
+
+void mmu_tlb_write_indexed(uint32_t index,tlb_item_t *tlb_item)
+{
+ tlb_item -> entry_lo[0].g |= tlb_item -> entry_lo[1].g;
+ tlb_item -> entry_lo[1].g |= tlb_item -> entry_lo[0].g;
+ mmu_tlb_set_index(index);
+ write_c0_entrylo0(reg_type_convert(tlb_item -> entry_lo[0],uint64_t));
+ write_c0_entrylo1(reg_type_convert(tlb_item -> entry_lo[1],uint64_t));
+ write_c0_entryhi(reg_type_convert(tlb_item -> entry_hi,uint64_t));
+ write_c0_pagemask(reg_type_convert(tlb_item -> page_mask,uint64_t));
+ tlb_write_indexed();
+ read_c0_entrylo0();
+}
+
+void mmu_tlb_write_random(tlb_item_t *tlb_item)
+{
+ tlb_item -> entry_lo[0].g |= tlb_item -> entry_lo[1].g;
+ tlb_item -> entry_lo[1].g |= tlb_item -> entry_lo[0].g;
+ write_c0_entrylo0(reg_type_convert(tlb_item -> entry_lo[0],uint64_t));
+ write_c0_entrylo1(reg_type_convert(tlb_item -> entry_lo[1],uint64_t));
+ write_c0_entryhi(reg_type_convert(tlb_item -> entry_hi,uint64_t));
+ write_c0_pagemask(reg_type_convert(tlb_item -> page_mask,uint64_t));
+ tlb_write_random();
+ read_c0_entrylo0();
+}
+
+void mmu_tlb_read(uint32_t index,tlb_item_t *tlb_item)
+{
+ mmu_tlb_set_index(index);
+ tlb_read();
+ uint64_t entrylo[2];
+ uint64_t entryhi;
+ uint64_t page_mask;
+ entrylo[0] = read_c0_entrylo0();
+ entrylo[1] = read_c0_entrylo1();
+ entryhi = read_c0_entryhi();
+ page_mask = read_c0_pagemask();
+ tlb_item -> entry_lo[0] = reg_type_convert(entrylo[0],entry_lo_t);
+ tlb_item -> entry_lo[1] = reg_type_convert(entrylo[1],entry_lo_t);
+ tlb_item -> entry_hi = reg_type_convert(entryhi,entry_hi_t);
+ tlb_item -> page_mask = reg_type_convert(page_mask,page_mask_t);
+}
+
+uint32_t mmu_tlb_find(uint64_t vpn,uint32_t asid,uint32_t *index)
+{
+ entry_hi_t entry_hi;
+ entry_hi.r = (vpn >> 62) & 0x03;
+ entry_hi.vpn2 = (vpn >> 13) & 0x7FFFFFFU;
+ entry_hi.asid = asid & 0xFFU;
+ tlb_item_t tlb_item;
+ //mmu_tlb_read(6,&tlb_item);
+ //tlb_dump();
+ mmu_tlb_item_init(&tlb_item);
+ tlb_item.entry_lo[0].g = tlb_item.entry_lo[1].g = 1;
+ read_c0_entrylo0();//i don't know why,but if i don't read any register of mmu,tplb will be failed in qemu.
+ write_c0_entrylo0(reg_type_convert(tlb_item.entry_lo[0],uint64_t));
+ write_c0_entrylo1(reg_type_convert(tlb_item.entry_lo[1],uint64_t));
+ write_c0_entryhi(reg_type_convert(entry_hi,uint64_t));
+ //__asm__ __volatile__("ehb");
+ //read_c0_entryhi();
+ //rt_kprintf("entry_hi = %p\n",read_c0_entryhi());
+ tlb_probe();
+ *index = mmu_tlb_get_index();
+ return mmu_tlb_is_matched();
+}
+
+void mmu_tlb_item_init(tlb_item_t *tlb_item)
+{
+ memset(tlb_item,0,sizeof(tlb_item_t));
+ tlb_item -> entry_lo[0].c = 0x03;
+ tlb_item -> entry_lo[1].c = 0x03;
+}
+
+void mmu_set_map(uint64_t vpn,uint64_t ppn,page_mask_enum_t page_mask,uint32_t asid,uint32_t global)
+{
+ uint64_t page_mask_v = (uint64_t)page_mask;
+
+ /*if(page_mask_v & (1 << 13))
+ {
+ page_mask_v |= (1 << 12);
+ }*/
+
+ uint64_t lb = lowbit((~(page_mask_v)) << 12);
+ uint64_t pn_remained = ((~(page_mask_v)) << 12) | lb;
+ vpn &= pn_remained;
+ ppn &= pn_remained;
+ uint64_t odd_vpn = vpn | lb;
+ uint64_t even_vpn = vpn & (~lb);
+ uint32_t index;
+ tlb_item_t tlb_item,tlb2_item;
+
+ mmu_tlb_item_init(&tlb_item);
+ mmu_tlb_item_init(&tlb2_item);
+ tlb_item.page_mask.mask = page_mask;
+
+ if(mmu_tlb_find(vpn & (~lb),asid,&index))
+ {
+ mmu_tlb_read(index,&tlb_item);
+ mmu_tlb_write_indexed(index,&tlb2_item);
+ }
+
+ entry_lo_t *entry_lo = &tlb_item.entry_lo[vpn == even_vpn ? 0 : 1];
+ tlb_item.entry_lo[0].g = tlb_item.entry_lo[1].g = global;
+ entry_lo -> d = 1;
+ entry_lo -> ri = 0;
+ entry_lo -> xi = 0;
+ entry_lo -> v = 1;
+ entry_lo -> pfn = ppn >> 12;
+ tlb_item.entry_hi.r = (vpn >> 62) & 0x03;
+ tlb_item.entry_hi.vpn2 = (vpn >> 13) & 0x7FFFFFFU;
+ tlb_item.entry_hi.asid = asid & 0xFFU;
+ mmu_tlb_write_random(&tlb_item);
+}
+
+uint32_t mmu_tlb_get_random()
+{
+ return read_c0_random();
+}
+
+uint32_t mmu_tlb_get_index()
+{
+ return read_c0_index() & 0x3F;
+}
+
+void mmu_tlb_set_index(uint32_t index)
+{
+ write_c0_index(index & 0x3F);
+}
+
+uint32_t mmu_tlb_is_matched()
+{
+ return (read_c0_index() & 0x80000000) == 0;
+}
+
+uint64_t mmu_tlb_get_bad_vaddr()
+{
+ return read_c0_badvaddr();
+}
+
+void tlb_dump()
+{
+ uint32_t max_index = mmu_get_max_tlb_index();
+ //uint32_t max_index = 10;
+ uint32_t entry;
+ tlb_item_t tlb_item;
+
+ for(entry = 0;entry <= max_index;entry++)
+ {
+ mmu_tlb_read(entry,&tlb_item);
+ //mmu_tlb_write_indexed(entry,&tlb_item);
+ //mmu_tlb_read(entry,&tlb_item);
+ rt_kprintf("vpn = 0x%p,ppn0 = 0x%p,ppn1 = 0x%p\n",(uint64_t)tlb_item.entry_hi.vpn2 << 13 | (uint64_t)tlb_item.entry_hi.asid << 62,(uint64_t)tlb_item.entry_lo[0].pfn << 12,(uint64_t)tlb_item.entry_lo[1].pfn << 12);
+ rt_kprintf("v = %d,d = %d,g = %d,ri = %d,xi = %d,c = %d\n",tlb_item.entry_lo[0].v,tlb_item.entry_lo[0].d,tlb_item.entry_lo[0].g,tlb_item.entry_lo[0].ri,tlb_item.entry_lo[0].xi,tlb_item.entry_lo[0].c);
+ rt_kprintf("v = %d,d = %d,g = %d,ri = %d,xi = %d,c = %d\n",tlb_item.entry_lo[1].v,tlb_item.entry_lo[1].d,tlb_item.entry_lo[1].g,tlb_item.entry_lo[1].ri,tlb_item.entry_lo[1].xi,tlb_item.entry_lo[1].c);
+ }
+}
diff --git a/libcpu/mips/gs264/mips_mmu.h b/libcpu/mips/gs264/mips_mmu.h
new file mode 100644
index 0000000000..fcbcef3621
--- /dev/null
+++ b/libcpu/mips/gs264/mips_mmu.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-07-26 lizhirui the first version
+ */
+#ifndef __MIPS_MMU_H__
+#define __MIPS_MMU_H__
+
+typedef enum cpu_mode_t
+{
+ CPU_MODE_KERNEL = 0x00,
+ CPU_MODE_SUPERVISOR = 0x01,
+ CPU_MODE_USER = 0x02
+}cpu_mode_t;
+
+typedef enum page_mask_enum_t
+{
+ PAGE_MASK_4KB = 0x00,
+ PAGE_MASK_16KB = 0x03,
+ PAGE_MASK_64KB = 0x0F,
+ PAGE_MASK_256KB = 0x3F,
+ PAGE_MASK_1MB = 0xFF,
+ PAGE_MASK_4MB = 0x3FF,
+ PAGE_MASK_16MB = 0xFFF,
+ PAGE_MASK_64MB = 0x3FFF,
+ PAGE_MASK_256MB = 0xFFFF,
+ PAGE_MASK_1GB = 0x3FFFF
+}page_mask_enum_t;
+
+typedef struct page_mask_t
+{
+ uint64_t : 11;
+ uint64_t : 2;
+ uint64_t mask : 18;
+ uint64_t : 33;
+}page_mask_t;
+
+typedef struct entry_lo_t
+{
+ uint64_t g : 1;
+ uint64_t v : 1;
+ uint64_t d : 1;
+ uint64_t c : 3;
+ uint64_t pfn : 24;
+ uint64_t pfnx : 3;
+ uint64_t : 29;
+ uint64_t xi : 1;
+ uint64_t ri : 1;
+}entry_lo_t;
+
+typedef struct entry_hi_t
+{
+ uint64_t asid : 8;
+ uint64_t : 5;
+ uint64_t vpn2 : 27;
+ uint64_t : 22;
+ uint64_t r : 2;
+}entry_hi_t;
+
+typedef struct tlb_item_t
+{
+ entry_lo_t entry_lo[2];
+ entry_hi_t entry_hi;
+ page_mask_t page_mask;
+}tlb_item_t;
+
+#define read_c0_diag() __read_32bit_c0_register($22, 0)
+#define write_c0_diag(val) __write_32bit_c0_register($22, 0, val)
+#define read_c0_badvaddr() __read_64bit_c0_register($8, 0)
+#define read_c0_random() __read_32bit_c0_register($1, 0)
+
+#define reg_type_convert(variable,new_type) *((new_type *)(&variable))
+#define lowbit(x) ((x) & (-(x)))
+
+void mmu_init();
+void mmu_set_cpu_mode(cpu_mode_t cpu_mode);
+cpu_mode_t mmu_get_cpu_mode();
+void mmu_clear_tlb();
+void mmu_clear_itlb();
+uint32_t mmu_get_max_tlb_index();
+void mmu_tlb_write_indexed(uint32_t index,tlb_item_t *tlb_item);
+void mmu_tlb_write_random(tlb_item_t *tlb_item);
+void mmu_tlb_read(uint32_t index,tlb_item_t *tlb_item);
+uint32_t mmu_tlb_find(uint64_t vpn,uint32_t asid,uint32_t *index);
+void mmu_tlb_item_init(tlb_item_t *tlb_item);
+void mmu_set_map(uint64_t vpn,uint64_t ppn,page_mask_enum_t page_mask,uint32_t asid,uint32_t global);
+uint32_t mmu_tlb_get_random();
+uint32_t mmu_tlb_get_index();
+void mmu_tlb_set_index(uint32_t index);
+uint32_t mmu_tlb_is_matched();
+uint64_t mmu_tlb_get_bad_vaddr();
+
+void tlb_dump();
+
+#endif \ No newline at end of file
diff --git a/libcpu/mips/gs264/mipscfg.c b/libcpu/mips/gs264/mipscfg.c
new file mode 100644
index 0000000000..b2aed120ae
--- /dev/null
+++ b/libcpu/mips/gs264/mipscfg.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-07-28 lizhirui first version
+ */
+#include <rtthread.h>
+#include <mips.h>
+
+mips32_core_cfg_t g_mips_core =
+{
+ 64, /* icache_line_size */
+ 128, /* icache_lines_per_way */
+ 4, /* icache_ways */
+ 32768,
+ 64, /* dcache_line_size */
+ 128, /* dcache_lines_per_way */
+ 4, /* dcache_ways */
+ 32768,
+ 64, /* max_tlb_entries */
+};
+
+static rt_uint16_t m_pow(rt_uint16_t b, rt_uint16_t n)
+{
+ rt_uint16_t rets = 1;
+
+ while (n--)
+ rets *= b;
+
+ return rets;
+}
+
+static rt_uint16_t m_log2(rt_uint16_t b)
+{
+ rt_uint16_t rets = 0;
+
+ while (b != 1)
+ {
+ b /= 2;
+ rets++;
+ }
+
+ return rets;
+}
+
+/**
+ * read core attribute
+ */
+void mips32_cfg_init(void)
+{
+ rt_uint16_t val;
+ rt_uint32_t cp0_config1;
+
+ cp0_config1 = read_c0_config();
+ if (cp0_config1 & 0x80000000)
+ {
+ cp0_config1 = read_c0_config1();
+
+ val = (cp0_config1 & (7<<22))>>22;
+ g_mips_core.icache_lines_per_way = 64 * m_pow(2, val);
+ val = (cp0_config1 & (7<<19))>>19;
+ g_mips_core.icache_line_size = 2 * m_pow(2, val);
+ val = (cp0_config1 & (7<<16))>>16;
+ g_mips_core.icache_ways = val + 1;
+
+ val = (cp0_config1 & (7<<13))>>13;
+ g_mips_core.dcache_lines_per_way = 64 * m_pow(2, val);
+ val = (cp0_config1 & (7<<10))>>10;
+ g_mips_core.dcache_line_size = 2 * m_pow(2, val);
+ val = (cp0_config1 & (7<<7))>>7;
+ g_mips_core.dcache_ways = val + 1;
+
+ val = (cp0_config1 & (0x3F<<25))>>25;
+ g_mips_core.max_tlb_entries = val + 1;
+ }
+}
diff --git a/libcpu/mips/gs264/mmu.c b/libcpu/mips/gs264/mmu.c
new file mode 100644
index 0000000000..b5bedace50
--- /dev/null
+++ b/libcpu/mips/gs264/mmu.c
@@ -0,0 +1,819 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-01-10 bernard porting to AM1808
+ * 2020-07-26 lizhirui porting to ls2k
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <board.h>
+
+#include "cache.h"
+#include "mips_mmu.h"
+#include "mmu.h"
+
+void *current_mmu_table = RT_NULL;
+
+void *mmu_table_get()
+{
+ return current_mmu_table;
+}
+
+void switch_mmu(void *mmu_table)
+{
+ current_mmu_table = mmu_table;
+
+ mmu_clear_tlb();
+ mmu_clear_itlb();
+}
+
+/* dump 2nd level page table */
+void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb)
+{
+ int i;
+ int fcnt = 0;
+
+ for (i = 0; i < 256; i++)
+ {
+ rt_uint32_t pte2 = ptb[i];
+ if ((pte2 & 0x3) == 0)
+ {
+ if (fcnt == 0)
+ rt_kprintf(" ");
+ rt_kprintf("%04x: ", i);
+ fcnt++;
+ if (fcnt == 16)
+ {
+ rt_kprintf("fault\n");
+ fcnt = 0;
+ }
+ continue;
+ }
+ if (fcnt != 0)
+ {
+ rt_kprintf("fault\n");
+ fcnt = 0;
+ }
+
+ rt_kprintf(" %04x: %x: ", i, pte2);
+ if ((pte2 & 0x3) == 0x1)
+ {
+ rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n",
+ ((pte2 >> 7) | (pte2 >> 4))& 0xf,
+ (pte2 >> 15) & 0x1,
+ ((pte2 >> 10) | (pte2 >> 2)) & 0x1f);
+ }
+ else
+ {
+ rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n",
+ ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1,
+ ((pte2 >> 4) | (pte2 >> 2)) & 0x1f);
+ }
+ }
+}
+
+void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb)
+{
+ int i;
+ int fcnt = 0;
+
+ rt_kprintf("page table@%p\n", ptb);
+ for (i = 0; i < 1024*4; i++)
+ {
+ rt_uint32_t pte1 = ptb[i];
+ if ((pte1 & 0x3) == 0)
+ {
+ rt_kprintf("%03x: ", i);
+ fcnt++;
+ if (fcnt == 16)
+ {
+ rt_kprintf("fault\n");
+ fcnt = 0;
+ }
+ continue;
+ }
+ if (fcnt != 0)
+ {
+ rt_kprintf("fault\n");
+ fcnt = 0;
+ }
+
+ rt_kprintf("%03x: %08x: ", i, pte1);
+ if ((pte1 & 0x3) == 0x3)
+ {
+ rt_kprintf("LPAE\n");
+ }
+ else if ((pte1 & 0x3) == 0x1)
+ {
+ rt_kprintf("pte,ns:%d,domain:%d\n",
+ (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf);
+ /*
+ *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000)
+ * - 0x80000000 + 0xC0000000));
+ */
+ }
+ else if (pte1 & (1 << 18))
+ {
+ rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n",
+ (pte1 >> 19) & 0x1,
+ ((pte1 >> 13) | (pte1 >> 10))& 0xf,
+ (pte1 >> 4) & 0x1,
+ ((pte1 >> 10) | (pte1 >> 2)) & 0x1f);
+ }
+ else
+ {
+ rt_kprintf("section,ns:%d,ap:%x,"
+ "xn:%d,texcb:%02x,domain:%d\n",
+ (pte1 >> 19) & 0x1,
+ ((pte1 >> 13) | (pte1 >> 10))& 0xf,
+ (pte1 >> 4) & 0x1,
+ (((pte1 & (0x7 << 12)) >> 10) |
+ ((pte1 & 0x0c) >> 2)) & 0x1f,
+ (pte1 >> 5) & 0xf);
+ }
+ }
+}
+
+/* level1 page table, each entry for 1MB memory. */
+volatile unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024)));
+void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,
+ rt_uint32_t vaddrEnd,
+ rt_uint32_t paddrStart,
+ rt_uint32_t attr)
+{
+ volatile rt_uint32_t *pTT;
+ volatile int i, nSec;
+ pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20);
+ nSec = (vaddrEnd >> 20) - (vaddrStart >> 20);
+ for(i = 0; i <= nSec; i++)
+ {
+ *pTT = attr | (((paddrStart >> 20) + i) << 20);
+ pTT++;
+ }
+}
+
+unsigned long rt_hw_set_domain_register(unsigned long domain_val)
+{
+ unsigned long old_domain;
+
+ //asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain));
+ //asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory");
+
+ return old_domain;
+}
+
+void rt_hw_cpu_dcache_clean(void *addr, int size);
+void rt_hw_init_mmu_table(struct mem_desc *mdesc, rt_uint32_t size)
+{
+ /* set page table */
+ for(; size > 0; size--)
+ {
+ rt_hw_mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
+ mdesc->paddr_start, mdesc->attr);
+ mdesc++;
+ }
+ rt_hw_cpu_dcache_clean((void*)MMUTable, sizeof MMUTable);
+}
+
+void rt_hw_mmu_init(void)
+{
+ rt_cpu_dcache_clean_flush();
+ rt_cpu_icache_flush();
+ rt_hw_cpu_dcache_disable();
+ rt_hw_cpu_icache_disable();
+ rt_cpu_mmu_disable();
+
+ /*rt_hw_cpu_dump_page_table(MMUTable);*/
+ rt_hw_set_domain_register(0x55555555);
+
+ rt_cpu_tlb_set(MMUTable);
+
+ rt_cpu_mmu_enable();
+
+ rt_hw_cpu_icache_enable();
+ rt_hw_cpu_dcache_enable();
+}
+
+/*
+ mem map
+*/
+
+void rt_hw_cpu_dcache_clean(void *addr, int size);
+
+int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void* v_address, size_t size, size_t *vtable, size_t pv_off)
+{
+ size_t l1_off, va_s, va_e;
+ rt_base_t level;
+
+ if (!mmu_info || !vtable)
+ {
+ return -1;
+ }
+
+ va_s = (size_t)v_address;
+ va_e = (size_t)v_address + size - 1;
+
+ if ( va_e < va_s)
+ {
+ return -1;
+ }
+
+ va_s >>= ARCH_SECTION_SHIFT;
+ va_e >>= ARCH_SECTION_SHIFT;
+
+ if (va_s == 0)
+ {
+ return -1;
+ }
+
+ level = rt_hw_interrupt_disable();
+
+ for (l1_off = va_s; l1_off <= va_e; l1_off++)
+ {
+ size_t v = vtable[l1_off];
+
+ if (v & ARCH_MMU_USED_MASK)
+ {
+ rt_kprintf("Error:vtable[%d] = 0x%p(is not zero),va_s = 0x%p,va_e = 0x%p!\n",l1_off,v,va_s,va_e);
+ rt_hw_interrupt_enable(level);
+ return -1;
+ }
+ }
+
+ mmu_info->vtable = vtable;
+ mmu_info->vstart = va_s;
+ mmu_info->vend = va_e;
+ mmu_info->pv_off = pv_off;
+
+ rt_hw_interrupt_enable(level);
+
+ return 0;
+}
+
+static size_t find_vaddr(rt_mmu_info *mmu_info, int pages)
+{
+ size_t l1_off, l2_off;
+ size_t *mmu_l1, *mmu_l2;
+ size_t find_off = 0;
+ size_t find_va = 0;
+ int n = 0;
+
+ if (!pages)
+ {
+ return 0;
+ }
+
+ if (!mmu_info)
+ {
+ return 0;
+ }
+
+ for (l1_off = mmu_info->vstart; l1_off <= mmu_info->vend; l1_off++)
+ {
+ mmu_l1 = (size_t*)mmu_info->vtable + l1_off;
+ if (*mmu_l1 & ARCH_MMU_USED_MASK)
+ {
+ mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off);
+ for (l2_off = 0; l2_off < (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE); l2_off++)
+ {
+ if (*(mmu_l2 + l2_off) & ARCH_MMU_USED_MASK)
+ {
+ /* in use */
+ n = 0;
+ }
+ else
+ {
+ if (!n)
+ {
+ find_va = l1_off;
+ find_off = l2_off;
+ }
+ n++;
+ if (n >= pages)
+ {
+ return (find_va << ARCH_SECTION_SHIFT) + (find_off << ARCH_PAGE_SHIFT);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!n)
+ {
+ find_va = l1_off;
+ find_off = 0;
+ }
+ n += (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE);
+ if (n >= pages)
+ {
+ return (find_va << ARCH_SECTION_SHIFT) + (find_off << ARCH_PAGE_SHIFT);
+ }
+ }
+ }
+ return 0;
+}
+
+#ifdef RT_USING_USERSPACE
+static int check_vaddr(rt_mmu_info *mmu_info, void *va, int pages)
+{
+ size_t loop_va = (size_t)va & ~ARCH_PAGE_MASK;
+ size_t l1_off, l2_off;
+ size_t *mmu_l1, *mmu_l2;
+
+ if (!pages)
+ {
+ return -1;
+ }
+
+ if (!mmu_info)
+ {
+ return -1;
+ }
+
+ while (pages--)
+ {
+ l1_off = (loop_va >> ARCH_SECTION_SHIFT);
+ l2_off = ((loop_va & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT);
+ mmu_l1 = (size_t*)mmu_info->vtable + l1_off;
+
+ if (*mmu_l1 & ARCH_MMU_USED_MASK)
+ {
+ mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off);
+ if (*(mmu_l2 + l2_off) & ARCH_MMU_USED_MASK)
+ {
+ return -1;
+ }
+ }
+ loop_va += ARCH_PAGE_SIZE;
+ }
+ return 0;
+}
+#endif
+
+static void __rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t npages)
+{
+ size_t loop_va = (size_t)v_addr & ~ARCH_PAGE_MASK;
+ size_t l1_off, l2_off;
+ size_t *mmu_l1, *mmu_l2;
+ size_t *ref_cnt;
+
+ if (!mmu_info)
+ {
+ return;
+ }
+
+ while (npages--)
+ {
+ l1_off = (loop_va >> ARCH_SECTION_SHIFT);
+ if (l1_off < mmu_info->vstart || l1_off > mmu_info->vend)
+ {
+ return;
+ }
+
+ l2_off = ((loop_va & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT);
+ mmu_l1 = (size_t*)mmu_info->vtable + l1_off;
+
+ if (*mmu_l1 & ARCH_MMU_USED_MASK)
+ {
+ mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off);
+ }
+ else
+ {
+ return;
+ }
+
+ if (*(mmu_l2 + l2_off) & ARCH_MMU_USED_MASK)
+ {
+ *(mmu_l2 + l2_off) = 0;
+ /* cache maintain */
+ rt_hw_cpu_dcache_clean(mmu_l2 + l2_off, 4);
+
+ ref_cnt = mmu_l2 + (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE);
+ (*ref_cnt)--;
+ if (!*ref_cnt)
+ {
+#ifdef RT_USING_USERSPACE
+ rt_pages_free(mmu_l2, 0);
+#else
+ rt_free_align(mmu_l2);
+#endif
+ *mmu_l1 = 0;
+
+ /* cache maintain */
+ rt_hw_cpu_dcache_clean(mmu_l1, 4);
+ }
+ }
+ loop_va += ARCH_PAGE_SIZE;
+ }
+}
+
+static int __rt_hw_mmu_map(rt_mmu_info *mmu_info, void* v_addr, void* p_addr, size_t npages, size_t attr)
+{
+ size_t loop_va = (size_t)v_addr & ~ARCH_PAGE_MASK;
+ size_t loop_pa = (size_t)p_addr & ~ARCH_PAGE_MASK;
+ size_t l1_off, l2_off;
+ size_t *mmu_l1, *mmu_l2;
+ size_t *ref_cnt;
+
+ if (!mmu_info)
+ {
+ return -1;
+ }
+
+ while (npages--)
+ {
+ l1_off = (loop_va >> ARCH_SECTION_SHIFT);
+ l2_off = ((loop_va & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT);
+ mmu_l1 = (size_t*)mmu_info->vtable + l1_off;
+
+ if (*mmu_l1 & ARCH_MMU_USED_MASK)
+ {
+ mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off);
+ }
+ else
+ {
+#ifdef RT_USING_USERSPACE
+ mmu_l2 = (size_t*)rt_pages_alloc(0);
+#else
+ mmu_l2 = (size_t*)rt_malloc_align(ARCH_PAGE_TBL_SIZE * 2, ARCH_PAGE_TBL_SIZE);
+#endif
+ if (mmu_l2)
+ {
+ rt_memset(mmu_l2, 0, ARCH_PAGE_TBL_SIZE * 2);
+ /* cache maintain */
+ rt_hw_cpu_dcache_clean(mmu_l2, ARCH_PAGE_TBL_SIZE);
+
+ *mmu_l1 = (((size_t)mmu_l2 + mmu_info->pv_off) | 0x1);
+ /* cache maintain */
+ rt_hw_cpu_dcache_clean(mmu_l1, 4);
+ }
+ else
+ {
+ /* error, unmap and quit */
+ __rt_hw_mmu_unmap(mmu_info, v_addr, npages);
+ return -1;
+ }
+ }
+
+ ref_cnt = mmu_l2 + (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE);
+ (*ref_cnt)++;
+
+ *(mmu_l2 + l2_off) = (loop_pa | attr);
+ /* cache maintain */
+ rt_hw_cpu_dcache_clean(mmu_l2 + l2_off, 4);
+
+ loop_va += ARCH_PAGE_SIZE;
+ loop_pa += ARCH_PAGE_SIZE;
+ }
+ return 0;
+}
+
+static void rt_hw_cpu_tlb_invalidate(void)
+{
+ mmu_clear_tlb();
+ mmu_clear_itlb();
+}
+
+#ifdef RT_USING_USERSPACE
+void *_rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr)
+{
+ size_t pa_s, pa_e;
+ size_t vaddr;
+ int pages;
+ int ret;
+
+ if (!size)
+ {
+ return 0;
+ }
+ pa_s = (size_t)p_addr;
+ pa_e = (size_t)p_addr + size - 1;
+ pa_s >>= ARCH_PAGE_SHIFT;
+ pa_e >>= ARCH_PAGE_SHIFT;
+ pages = pa_e - pa_s + 1;
+ if (v_addr)
+ {
+ vaddr = (size_t)v_addr;
+ pa_s = (size_t)p_addr;
+ if ((vaddr & ARCH_PAGE_MASK) != (pa_s & ARCH_PAGE_MASK))
+ {
+ return 0;
+ }
+ vaddr &= ~ARCH_PAGE_MASK;
+ if (check_vaddr(mmu_info, (void*)vaddr, pages) != 0)
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ vaddr = find_vaddr(mmu_info, pages);
+ }
+ if (vaddr) {
+ ret = __rt_hw_mmu_map(mmu_info, (void*)vaddr, p_addr, pages, attr);
+ if (ret == 0)
+ {
+ rt_hw_cpu_tlb_invalidate();
+ return (void*)(vaddr + ((size_t)p_addr & ARCH_PAGE_MASK));
+ }
+ }
+ return 0;
+}
+#else
+void *_rt_hw_mmu_map(rt_mmu_info *mmu_info, void* p_addr, size_t size, size_t attr)
+{
+ size_t pa_s, pa_e;
+ size_t vaddr;
+ int pages;
+ int ret;
+
+ pa_s = (size_t)p_addr;
+ pa_e = (size_t)p_addr + size - 1;
+ pa_s >>= ARCH_PAGE_SHIFT;
+ pa_e >>= ARCH_PAGE_SHIFT;
+ pages = pa_e - pa_s + 1;
+ vaddr = find_vaddr(mmu_info, pages);
+ if (vaddr) {
+ ret = __rt_hw_mmu_map(mmu_info, (void*)vaddr, p_addr, pages, attr);
+ if (ret == 0)
+ {
+ rt_hw_cpu_tlb_invalidate();
+ return (void*)(vaddr + ((size_t)p_addr & ARCH_PAGE_MASK));
+ }
+ }
+ return 0;
+}
+#endif
+
+#ifdef RT_USING_USERSPACE
+static int __rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void* v_addr, size_t npages, size_t attr)
+{
+ size_t loop_va = (size_t)v_addr & ~ARCH_PAGE_MASK;
+ size_t loop_pa;
+ size_t l1_off, l2_off;
+ size_t *mmu_l1, *mmu_l2;
+ size_t *ref_cnt;
+
+ if (!mmu_info)
+ {
+ return -1;
+ }
+
+ while (npages--)
+ {
+ loop_pa = (size_t)rt_pages_alloc(0) + mmu_info->pv_off;
+ if (!loop_pa)
+ goto err;
+
+ //rt_kprintf("vaddr = %08x is mapped to paddr = %08x\n",v_addr,loop_pa);
+ l1_off = (loop_va >> ARCH_SECTION_SHIFT);
+ l2_off = ((loop_va & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT);
+ mmu_l1 = (size_t*)mmu_info->vtable + l1_off;
+
+ if (*mmu_l1 & ARCH_MMU_USED_MASK)
+ {
+ mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off);
+ }
+ else
+ {
+ //mmu_l2 = (size_t*)rt_malloc_align(ARCH_PAGE_TBL_SIZE * 2, ARCH_PAGE_TBL_SIZE);
+ mmu_l2 = (size_t*)rt_pages_alloc(0);
+ if (mmu_l2)
+ {
+ rt_memset(mmu_l2, 0, ARCH_PAGE_TBL_SIZE * 2);
+ /* cache maintain */
+ rt_hw_cpu_dcache_clean(mmu_l2, ARCH_PAGE_TBL_SIZE);
+
+ *mmu_l1 = (((size_t)mmu_l2 + mmu_info->pv_off) | 0x1);
+ /* cache maintain */
+ rt_hw_cpu_dcache_clean(mmu_l1, 4);
+ }
+ else
+ goto err;
+ }
+
+ ref_cnt = mmu_l2 + (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE);
+ (*ref_cnt)++;
+
+ //loop_pa += mmu_info->pv_off;
+ *(mmu_l2 + l2_off) = (loop_pa | attr);
+ /* cache maintain */
+ rt_hw_cpu_dcache_clean(mmu_l2 + l2_off, 4);
+
+ loop_va += ARCH_PAGE_SIZE;
+ }
+ return 0;
+err:
+ {
+ /* error, unmap and quit */
+ int i;
+ void *va, *pa;
+
+ va = (void*)((size_t)v_addr & ~ARCH_PAGE_MASK);
+ for (i = 0; i < npages; i++)
+ {
+ pa = rt_hw_mmu_v2p(mmu_info, va);
+ pa -= mmu_info->pv_off;
+ rt_pages_free(pa, 0);
+ va += ARCH_PAGE_SIZE;
+ }
+
+ __rt_hw_mmu_unmap(mmu_info, v_addr, npages);
+ return -1;
+ }
+}
+
+void *_rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr)
+{
+ size_t vaddr;
+ size_t offset;
+ int pages;
+ int ret;
+
+ if (!size)
+ {
+ return 0;
+ }
+ offset = (size_t)v_addr & ARCH_PAGE_MASK;
+ size += (offset + ARCH_PAGE_SIZE - 1);
+ pages = (size >> ARCH_PAGE_SHIFT);
+ if (v_addr)
+ {
+ vaddr = (size_t)v_addr;
+ vaddr &= ~ARCH_PAGE_MASK;
+ if (check_vaddr(mmu_info, (void*)vaddr, pages) != 0)
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ vaddr = find_vaddr(mmu_info, pages);
+ }
+ if (vaddr) {
+ ret = __rt_hw_mmu_map_auto(mmu_info, (void*)vaddr, pages, attr);
+ if (ret == 0)
+ {
+ rt_hw_cpu_tlb_invalidate();
+ return (void*)vaddr + offset;
+ }
+ }
+ return 0;
+}
+#endif
+
+void _rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size)
+{
+ size_t va_s, va_e;
+ int pages;
+
+ va_s = (size_t)v_addr;
+ va_e = (size_t)v_addr + size - 1;
+ va_s >>= ARCH_PAGE_SHIFT;
+ va_e >>= ARCH_PAGE_SHIFT;
+ pages = va_e - va_s + 1;
+ __rt_hw_mmu_unmap(mmu_info, v_addr, pages);
+ rt_hw_cpu_tlb_invalidate();
+}
+
+//va --> pa
+void *rt_hw_kernel_virt_to_phys(void *v_addr, size_t size)
+{
+ void *p_addr = 0;
+
+ return p_addr;
+}
+
+//pa --> va
+void *rt_hw_kernel_phys_to_virt(void *p_addr, size_t size)
+{
+ void *v_addr = 0;
+
+ #ifdef RT_USING_USERSPACE
+ extern rt_mmu_info mmu_info;
+ v_addr = rt_hw_mmu_map(&mmu_info, 0, p_addr, size, MMU_MAP_K_RW);
+ #else
+ v_addr = p_addr;
+ #endif
+
+ return v_addr;
+}
+
+#ifdef RT_USING_USERSPACE
+void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr)
+{
+ void *ret;
+ rt_base_t level;
+
+ level = rt_hw_interrupt_disable();
+ ret = _rt_hw_mmu_map(mmu_info, v_addr, p_addr, size, attr);
+ rt_hw_interrupt_enable(level);
+ return ret;
+}
+
+void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr)
+{
+ void *ret;
+ rt_base_t level;
+
+ level = rt_hw_interrupt_disable();
+ ret = _rt_hw_mmu_map_auto(mmu_info, v_addr, size, attr);
+ rt_hw_interrupt_enable(level);
+ return ret;
+}
+#endif
+
+void rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size)
+{
+ rt_base_t level;
+
+ level = rt_hw_interrupt_disable();
+ _rt_hw_mmu_unmap(mmu_info, v_addr, size);
+ rt_hw_interrupt_enable(level);
+}
+
+void *_rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr)
+{
+ size_t l1_off, l2_off;
+ size_t *mmu_l1, *mmu_l2;
+ size_t tmp;
+ size_t pa;
+
+ l1_off = (size_t)v_addr >> ARCH_SECTION_SHIFT;
+
+ if (!mmu_info)
+ {
+ return (void*)0;
+ }
+
+ mmu_l1 = (size_t*)mmu_info->vtable + l1_off;
+
+ tmp = *mmu_l1;
+
+ switch (tmp & ARCH_MMU_USED_MASK)
+ {
+ case 0: /* not used */
+ break;
+ case 1: /* page table */
+ mmu_l2 = (size_t *)((tmp & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off);
+ l2_off = (((size_t)v_addr & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT);
+ pa = *(mmu_l2 + l2_off);
+ if (pa & ARCH_MMU_USED_MASK)
+ {
+ if ((pa & ARCH_MMU_USED_MASK) == 1)
+ {
+ /* lage page, not support */
+ break;
+ }
+ pa &= ~(ARCH_PAGE_MASK);
+ pa += ((size_t)v_addr & ARCH_PAGE_MASK);
+ return (void*)pa;
+ }
+ break;
+ case 2:
+ case 3:
+ /* section */
+ if (tmp & ARCH_TYPE_SUPERSECTION)
+ {
+ /* super section, not support */
+ break;
+ }
+ pa = (tmp & ~ARCH_SECTION_MASK);
+ pa += ((size_t)v_addr & ARCH_SECTION_MASK);
+ return (void*)pa;
+ }
+ return (void*)0;
+}
+
+void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr)
+{
+ void *ret;
+ rt_base_t level;
+
+ level = rt_hw_interrupt_disable();
+ ret = _rt_hw_mmu_v2p(mmu_info, v_addr);
+ rt_hw_interrupt_enable(level);
+ return ret;
+}
+
+#ifdef RT_USING_USERSPACE
+void init_mm_setup(unsigned int *mtbl, unsigned int size, unsigned int pv_off) {
+ unsigned int va;
+
+ for (va = 0; va < 0x1000; va++) {
+ unsigned int vaddr = (va << 20);
+ if (vaddr >= KERNEL_VADDR_START && vaddr - KERNEL_VADDR_START < size) {
+ mtbl[va] = ((va << 20) + pv_off) | NORMAL_MEM;
+ } else if (vaddr >= (KERNEL_VADDR_START + pv_off) && vaddr - (KERNEL_VADDR_START + pv_off) < size) {
+ mtbl[va] = (va << 20) | NORMAL_MEM;
+ } else {
+ mtbl[va] = 0;
+ }
+ }
+}
+#endif
diff --git a/libcpu/mips/gs264/mmu.h b/libcpu/mips/gs264/mmu.h
new file mode 100644
index 0000000000..2472bf975f
--- /dev/null
+++ b/libcpu/mips/gs264/mmu.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2019-03-25 quanzhao the first version
+ * 2020-07-26 lizhirui porting to ls2k
+ */
+#ifndef __MMU_H_
+#define __MMU_H_
+
+#include <rtthread.h>
+
+#define DESC_SEC (0x2)
+#define MEMWBWA ((1<<12)|(3<<2)) /* write back, write allocate */
+#define MEMWB (3<<2) /* write back, no write allocate */
+#define MEMWT (2<<2) /* write through, no write allocate */
+#define SHAREDEVICE (1<<2) /* shared device */
+#define STRONGORDER (0<<2) /* strong ordered */
+#define XN (1<<4) /* execute Never */
+#ifdef RT_USING_USERSPACE
+#define AP_RW (1<<10) /* supervisor=RW, user=No */
+#define AP_RO ((1<<10) |(1 << 15)) /* supervisor=RW, user=No */
+#else
+#define AP_RW (3<<10) /* supervisor=RW, user=RW */
+#define AP_RO ((2<<10) /* supervisor=RW, user=RO */
+#endif
+
+#define SHARED (1<<16) /* shareable */
+
+#define DOMAIN_FAULT (0x0)
+#define DOMAIN_CHK (0x1)
+#define DOMAIN_NOTCHK (0x3)
+#define DOMAIN0 (0x0<<5)
+#define DOMAIN1 (0x1<<5)
+
+#define DOMAIN0_ATTR (DOMAIN_CHK<<0)
+#define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
+
+/* device mapping type */
+#define DEVICE_MEM (SHARED|AP_RW|DOMAIN0|SHAREDEVICE|DESC_SEC|XN)
+/* normal memory mapping type */
+#define NORMAL_MEM (SHARED|AP_RW|DOMAIN0|MEMWBWA|DESC_SEC)
+
+#define STRONG_ORDER_MEM (SHARED|AP_RO|XN|DESC_SEC)
+
+struct mem_desc
+{
+ rt_uint32_t vaddr_start;
+ rt_uint32_t vaddr_end;
+ rt_uint32_t paddr_start;
+ rt_uint32_t attr;
+};
+
+#define MMU_MAP_MTBL_XN (1<<0)
+#define MMU_MAP_MTBL_A (1<<1)
+#define MMU_MAP_MTBL_B (1<<2)
+#define MMU_MAP_MTBL_C (1<<3)
+#define MMU_MAP_MTBL_AP01(x) (x<<4)
+#define MMU_MAP_MTBL_TEX(x) (x<<6)
+#define MMU_MAP_MTBL_AP2(x) (x<<9)
+#define MMU_MAP_MTBL_SHARE (1<<10)
+
+#define MMU_MAP_K_RO (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)
+#define MMU_MAP_K_RWCB (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)
+#define MMU_MAP_K_RW (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE)
+#define MMU_MAP_K_DEVICE (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE)
+#define MMU_MAP_U_RO (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(2)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)
+#define MMU_MAP_U_RWCB (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)
+#define MMU_MAP_U_RW (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE)
+#define MMU_MAP_U_DEVICE (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE)
+
+#define ARCH_SECTION_SHIFT 20
+#define ARCH_SECTION_SIZE (1 << ARCH_SECTION_SHIFT)
+#define ARCH_SECTION_MASK (ARCH_SECTION_SIZE - 1)
+#define ARCH_PAGE_SHIFT 14
+#define ARCH_PAGE_SIZE (1 << ARCH_PAGE_SHIFT)
+#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1)
+#define ARCH_PAGE_TBL_SHIFT 10
+#define ARCH_PAGE_TBL_SIZE (1 << ARCH_PAGE_TBL_SHIFT)
+#define ARCH_PAGE_TBL_MASK (ARCH_PAGE_TBL_SIZE - 1)
+
+#define ARCH_MMU_USED_MASK 3
+
+#define ARCH_TYPE_SUPERSECTION (1 << 18)
+
+typedef struct
+{
+ size_t *vtable;
+ size_t vstart;
+ size_t vend;
+ size_t pv_off;
+} rt_mmu_info;
+
+void *mmu_table_get();
+void switch_mmu(void *mmu_table);
+
+int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void* v_address, size_t size, size_t *vtable, size_t pv_off);
+#ifdef RT_USING_USERSPACE
+void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr);
+void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr);
+#else
+void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void* p_addr, size_t size, size_t attr);
+#endif
+void rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size);
+void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr);
+
+void *rt_hw_kernel_phys_to_virt(void *p_addr, size_t size);
+void *rt_hw_kernel_virt_to_phys(void *v_addr, size_t size);
+
+#endif
diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript
index 024cc5ba44..5055b533e6 100644
--- a/libcpu/risc-v/SConscript
+++ b/libcpu/risc-v/SConscript
@@ -10,10 +10,17 @@ group = []
list = os.listdir(cwd)
# add common code files
-if rtconfig.CPU != "nuclei":
- group = group + SConscript(os.path.join('common', 'SConscript'))
+if rtconfig.VENDOR == "t-head" :
+ group = group
+elif rtconfig.CPU == "nuclei" :
+ group = group
+else :
+ group = group + SConscript(os.path.join(cwd, 'common', 'SConscript'))
# cpu porting code files
-group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript'))
+if rtconfig.VENDOR == "t-head" :
+ group = group + SConscript(os.path.join(cwd, rtconfig.VENDOR, rtconfig.CPU, 'SConscript'))
+else :
+ group = group + SConscript(os.path.join(cwd, rtconfig.CPU, 'SConscript'))
Return('group')
diff --git a/libcpu/risc-v/nuclei/cpuport.c b/libcpu/risc-v/nuclei/cpuport.c
index fad9afdf4c..e456438f70 100644
--- a/libcpu/risc-v/nuclei/cpuport.c
+++ b/libcpu/risc-v/nuclei/cpuport.c
@@ -19,7 +19,7 @@
#define SYSTICK_TICK_CONST (SOC_TIMER_FREQ / RT_TICK_PER_SECOND)
/* Interrupt level for kernel systimer interrupt and software timer interrupt */
-#define RT_KERNEL_INTERRUPT_LEVEL 1
+#define RT_KERNEL_INTERRUPT_LEVEL 0
/* Initial CSR MSTATUS value when thread created */
#define RT_INITIAL_MSTATUS (MSTATUS_MPP | MSTATUS_MPIE | MSTATUS_FS_INITIAL)
diff --git a/libcpu/risc-v/t-head/e906/SConscript b/libcpu/risc-v/t-head/e906/SConscript
new file mode 100644
index 0000000000..2f698f530a
--- /dev/null
+++ b/libcpu/risc-v/t-head/e906/SConscript
@@ -0,0 +1,12 @@
+# RT-Thread building script for component
+
+from building import *
+
+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/t-head/e906/context_gcc.S b/libcpu/risc-v/t-head/e906/context_gcc.S
new file mode 100644
index 0000000000..2f5223ae63
--- /dev/null
+++ b/libcpu/risc-v/t-head/e906/context_gcc.S
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020/08/20 zx.chen The T-HEAD RISC-V CPU E906 porting implementation
+ */
+
+#include "cpuport.h"
+
+#ifdef RT_USING_SMP
+#define rt_hw_interrupt_disable rt_hw_local_irq_disable
+#define rt_hw_interrupt_enable rt_hw_local_irq_enable
+#endif
+
+/*
+ * Functions: vPortYield
+ */
+.global vPortYield
+.type vPortYield, %function
+vPortYield:
+ li t0, 0xE080100C
+ lb t1, (t0)
+ li t2, 0x01
+ or t1, t1, t2
+ sb t1, (t0)
+
+ ret
+
+
+
+/*
+ * #ifdef RT_USING_SMP
+ * void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
+ * #else
+ * void rt_hw_context_switch_to(rt_ubase_t to);
+ * #endif
+ * a0 --> to
+ * a1 --> to_thread
+ */
+ .globl rt_hw_context_switch_to
+rt_hw_context_switch_to:
+ /* save a0 to to_thread */
+ la t0, rt_interrupt_to_thread
+ STORE a0, (t0)
+
+ /* save 0 to from_thread */
+ la t0, rt_interrupt_from_thread
+ li t1, 0
+ STORE t1, (t0)
+
+ /* set rt_thread_switch_interrupt_flag=1 */
+ la t0, rt_thread_switch_interrupt_flag
+ li t1, 1
+ STORE t1, (t0)
+
+ /* enable mexstatus SPUSHEN and SPSWAPEN */
+#if ((CONFIG_CPU_E906==1) || (CONFIG_CPU_E906F==1) || (CONFIG_CPU_E906FD==1))
+ uint32_t mexstatus;
+ mexstatus = __get_MEXSTATUS();
+ mexstatus |= (0x2 << 16);
+ __set_MEXSTATUS(mexstatus);
+#endif
+
+ csrw mscratch, sp
+ /* set software interrupt */
+ li t0, 0xE080100C
+ lb t1, (t0)
+ li t2, 0x01
+ or t1, t1, t2
+ sb t1, (t0)
+
+ /* enable global interrup */
+ csrsi mstatus, 8
+
+ ret
+
+/*
+ * #ifdef RT_USING_SMP
+ * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
+ * #else
+ * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
+ * #endif
+ *
+ * a0 --> from
+ * a1 --> to
+ * a2 --> to_thread
+ */
+ .globl rt_hw_context_switch
+rt_hw_context_switch:
+ .globl rt_hw_context_switch_interrupt
+rt_hw_context_switch_interrupt:
+ /* check rt_thread_switch_interrupt_flag */
+ la t0, rt_thread_switch_interrupt_flag
+ lw t1, (t0)
+ li t2, 1
+ beq t1, t2, .reswitch
+ /* set rt_thread_switch_interrupt_flag=1 */
+ STORE t2, (t0)
+
+ /* update from_thread */
+ la t0, rt_interrupt_from_thread
+ STORE a0, (t0)
+
+.reswitch:
+ /* update to_thread */
+ la t0, rt_interrupt_to_thread
+ STORE a1, (t0)
+ /* set software interrupt */
+ li t0, 0xE080100C
+ lb t1, (t0)
+ li t2, 0x01
+ or t1, t1, t2
+ sb t1, (t0)
+
+ ret
+
+/*
+ * PendSV_Handler
+ */
+.global PendSV_Handler
+.type PendSV_Handler, %function
+PendSV_Handler:
+
+ /* check rt_thread_switch_interrupt_flag */
+ sw t0, (-4)(sp)
+ sw t1, (-8)(sp)
+ la t0, rt_thread_switch_interrupt_flag
+ lw t1, (t0)
+ beqz t1, .pendsv_exit
+
+ /* clear rt_thread_switch_interrupt_flag */
+ li t1, 0x0
+ sw t1, (t0)
+
+ /* check rt_interrupt_from_thread */
+ la t0, rt_interrupt_from_thread
+ lw t1, (t0)
+ beqz t1, .switch_to_thead
+
+ /* save from thread context */
+ lw t0, (-4)(sp)
+ lw t1, (-8)(sp)
+
+#ifdef ARCH_RISCV_FPU
+ addi sp, sp, -32 * FREGBYTES
+
+ FSTORE f0, 0 * FREGBYTES(sp)
+ FSTORE f1, 1 * FREGBYTES(sp)
+ FSTORE f2, 2 * FREGBYTES(sp)
+ FSTORE f3, 3 * FREGBYTES(sp)
+ FSTORE f4, 4 * FREGBYTES(sp)
+ FSTORE f5, 5 * FREGBYTES(sp)
+ FSTORE f6, 6 * FREGBYTES(sp)
+ FSTORE f7, 7 * FREGBYTES(sp)
+ FSTORE f8, 8 * FREGBYTES(sp)
+ FSTORE f9, 9 * FREGBYTES(sp)
+ FSTORE f10, 10 * FREGBYTES(sp)
+ FSTORE f11, 11 * FREGBYTES(sp)
+ FSTORE f12, 12 * FREGBYTES(sp)
+ FSTORE f13, 13 * FREGBYTES(sp)
+ FSTORE f14, 14 * FREGBYTES(sp)
+ FSTORE f15, 15 * FREGBYTES(sp)
+ FSTORE f16, 16 * FREGBYTES(sp)
+ FSTORE f17, 17 * FREGBYTES(sp)
+ FSTORE f18, 18 * FREGBYTES(sp)
+ FSTORE f19, 19 * FREGBYTES(sp)
+ FSTORE f20, 20 * FREGBYTES(sp)
+ FSTORE f21, 21 * FREGBYTES(sp)
+ FSTORE f22, 22 * FREGBYTES(sp)
+ FSTORE f23, 23 * FREGBYTES(sp)
+ FSTORE f24, 24 * FREGBYTES(sp)
+ FSTORE f25, 25 * FREGBYTES(sp)
+ FSTORE f26, 26 * FREGBYTES(sp)
+ FSTORE f27, 27 * FREGBYTES(sp)
+ FSTORE f28, 28 * FREGBYTES(sp)
+ FSTORE f29, 29 * FREGBYTES(sp)
+ FSTORE f30, 30 * FREGBYTES(sp)
+ FSTORE f31, 31 * FREGBYTES(sp)
+#endif
+
+ addi sp, sp, -32 * REGBYTES
+
+ STORE x1, 1 * REGBYTES(sp)
+ csrr x1, mepc
+ STORE x1, 0 * REGBYTES(sp)
+ csrr x1, mstatus
+ andi x1, x1, 8
+ beqz x1, .save_mpie
+ li x1, 0x80
+.save_mpie:
+ STORE x1, 2 * REGBYTES(sp)
+ /* x3 don't need save */
+ 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)
+
+ /* store from_thread sp */
+ la t0, rt_interrupt_from_thread
+ lw t0, (t0)
+ sw sp, (t0)
+
+.switch_to_thead:
+ /* restore to thread context
+ * sp(0) -> epc;
+ * sp(1) -> ra;
+ * sp(i) -> x(i+2)
+ */
+ la t0, rt_interrupt_to_thread
+ lw t0, (t0)
+ LOAD sp, (t0)
+
+ /* restore ra to mepc */
+ LOAD a1, 0 * REGBYTES(sp)
+ csrw mepc, a1
+ LOAD x1, 1 * REGBYTES(sp)
+
+ /* force to machin mode(MPP=11) */
+ li a1, 0x1880
+ csrs mstatus, a1
+ LOAD a1, 2 * REGBYTES(sp)
+ csrs mstatus, a1
+ /* x3 don't need restore */
+ 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, 32 * REGBYTES
+
+#ifdef ARCH_RISCV_FPU
+ FLOAD f0, 0 * FREGBYTES(sp)
+ FLOAD f1, 1 * FREGBYTES(sp)
+ FLOAD f2, 2 * FREGBYTES(sp)
+ FLOAD f3, 3 * FREGBYTES(sp)
+ FLOAD f4, 4 * FREGBYTES(sp)
+ FLOAD f5, 5 * FREGBYTES(sp)
+ FLOAD f6, 6 * FREGBYTES(sp)
+ FLOAD f7, 7 * FREGBYTES(sp)
+ FLOAD f8, 8 * FREGBYTES(sp)
+ FLOAD f9, 9 * FREGBYTES(sp)
+ FLOAD f10, 10 * FREGBYTES(sp)
+ FLOAD f11, 11 * FREGBYTES(sp)
+ FLOAD f12, 12 * FREGBYTES(sp)
+ FLOAD f13, 13 * FREGBYTES(sp)
+ FLOAD f14, 14 * FREGBYTES(sp)
+ FLOAD f15, 15 * FREGBYTES(sp)
+ FLOAD f16, 16 * FREGBYTES(sp)
+ FLOAD f17, 17 * FREGBYTES(sp)
+ FLOAD f18, 18 * FREGBYTES(sp)
+ FLOAD f19, 19 * FREGBYTES(sp)
+ FLOAD f20, 20 * FREGBYTES(sp)
+ FLOAD f21, 21 * FREGBYTES(sp)
+ FLOAD f22, 22 * FREGBYTES(sp)
+ FLOAD f23, 23 * FREGBYTES(sp)
+ FLOAD f24, 24 * FREGBYTES(sp)
+ FLOAD f25, 25 * FREGBYTES(sp)
+ FLOAD f26, 26 * FREGBYTES(sp)
+ FLOAD f27, 27 * FREGBYTES(sp)
+ FLOAD f28, 28 * FREGBYTES(sp)
+ FLOAD f29, 29 * FREGBYTES(sp)
+ FLOAD f30, 30 * FREGBYTES(sp)
+ FLOAD f31, 31 * FREGBYTES(sp)
+
+ addi sp, sp, 32 * FREGBYTES
+#endif
+
+.pendsv_exit:
+ mret
+
+
+
diff --git a/libcpu/risc-v/t-head/e906/cpuport.c b/libcpu/risc-v/t-head/e906/cpuport.c
new file mode 100644
index 0000000000..5597aa237a
--- /dev/null
+++ b/libcpu/risc-v/t-head/e906/cpuport.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020/08/20 zx.chen The T-HEAD RISC-V CPU E906 porting code.
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "cpuport.h"
+
+#ifndef RT_USING_SMP
+volatile rt_ubase_t rt_interrupt_from_thread = 0;
+volatile rt_ubase_t rt_interrupt_to_thread = 0;
+volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
+#endif
+
+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 mstatus; /* - machine 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 */
+#ifdef ARCH_RISCV_FPU
+ rv_floatreg_t f0; /* f0 */
+ rv_floatreg_t f1; /* f1 */
+ rv_floatreg_t f2; /* f2 */
+ rv_floatreg_t f3; /* f3 */
+ rv_floatreg_t f4; /* f4 */
+ rv_floatreg_t f5; /* f5 */
+ rv_floatreg_t f6; /* f6 */
+ rv_floatreg_t f7; /* f7 */
+ rv_floatreg_t f8; /* f8 */
+ rv_floatreg_t f9; /* f9 */
+ rv_floatreg_t f10; /* f10 */
+ rv_floatreg_t f11; /* f11 */
+ rv_floatreg_t f12; /* f12 */
+ rv_floatreg_t f13; /* f13 */
+ rv_floatreg_t f14; /* f14 */
+ rv_floatreg_t f15; /* f15 */
+ rv_floatreg_t f16; /* f16 */
+ rv_floatreg_t f17; /* f17 */
+ rv_floatreg_t f18; /* f18 */
+ rv_floatreg_t f19; /* f19 */
+ rv_floatreg_t f20; /* f20 */
+ rv_floatreg_t f21; /* f21 */
+ rv_floatreg_t f22; /* f22 */
+ rv_floatreg_t f23; /* f23 */
+ rv_floatreg_t f24; /* f24 */
+ rv_floatreg_t f25; /* f25 */
+ rv_floatreg_t f26; /* f26 */
+ rv_floatreg_t f27; /* f27 */
+ rv_floatreg_t f28; /* f28 */
+ rv_floatreg_t f29; /* f29 */
+ rv_floatreg_t f30; /* f30 */
+ rv_floatreg_t f31; /* f31 */
+#endif
+};
+
+/**
+ * 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;
+
+ 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->a0 = (rt_ubase_t)parameter;
+ frame->epc = (rt_ubase_t)tentry;
+
+ /* force to machine mode(MPP=11) and set MPIE to 1 */
+ frame->mstatus = 0x00007880;
+
+ return stk;
+}
+
+
+/**
+ * This function will disable global interrupt
+ *
+ * @param none
+ *
+ * @return zero
+ */
+
+rt_base_t rt_hw_interrupt_disable(void)
+{
+ __asm volatile("csrc mstatus, 8");
+ return 0;
+}
+
+/**
+ * This function will ennable global interrupt
+ *
+ * @param level not used
+ *
+ * @return none
+ */
+void rt_hw_interrupt_enable(rt_base_t level)
+{
+ __asm volatile("csrs mstatus, 8");
+}
+
+/** 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);
+ }
+}
diff --git a/libcpu/risc-v/t-head/e906/cpuport.h b/libcpu/risc-v/t-head/e906/cpuport.h
new file mode 100644
index 0000000000..90efc07653
--- /dev/null
+++ b/libcpu/risc-v/t-head/e906/cpuport.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-20 zx.chen The first version
+ */
+
+#ifndef CPUPORT_H__
+#define CPUPORT_H__
+
+#include <rtconfig.h>
+
+/* bytes of register width */
+#ifdef ARCH_RISCV_64
+#define DFSTORE fsd
+#define DFLOAD fld
+#define SFSTORE fsw
+#define SFLOAD flw
+#define STORE sd
+#define LOAD ld
+#define REGBYTES 8
+#define SFREGBYTES 4
+#define DFREGBYTES 8
+#else
+#define DFSTORE fsd
+#define DFLOAD fld
+#define SFSTORE fsw
+#define SFLOAD flw
+#define STORE sw
+#define LOAD lw
+
+#define REGBYTES 4
+#define SFREGBYTES 4
+#define DFREGBYTES 8
+#endif
+
+#ifdef ARCH_RISCV_FPU
+#ifdef ARCH_RISCV_FPU_D
+#define FSTORE fsd
+#define FLOAD fld
+#define FREGBYTES 8
+#define rv_floatreg_t rt_int64_t
+#endif
+#ifdef ARCH_RISCV_FPU_S
+#define FSTORE fsw
+#define FLOAD flw
+#define FREGBYTES 4
+#define rv_floatreg_t rt_int32_t
+#endif
+#endif
+
+#endif