diff options
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/Kconfig | 4 | ||||
| -rw-r--r-- | libcpu/mips/common/asm.h | 4 | ||||
| -rw-r--r-- | libcpu/mips/common/context_gcc.S | 21 | ||||
| -rw-r--r-- | libcpu/mips/common/exception.c | 50 | ||||
| -rw-r--r-- | libcpu/mips/common/exception_gcc.S | 8 | ||||
| -rw-r--r-- | libcpu/mips/common/stackframe.h | 12 | ||||
| -rw-r--r-- | libcpu/mips/gs264/cache.c | 70 | ||||
| -rw-r--r-- | libcpu/mips/gs264/cache.h | 24 | ||||
| -rw-r--r-- | libcpu/mips/gs264/cpuinit_gcc.S | 8 | ||||
| -rw-r--r-- | libcpu/mips/gs264/mips_mmu.c | 222 | ||||
| -rw-r--r-- | libcpu/mips/gs264/mips_mmu.h | 99 | ||||
| -rw-r--r-- | libcpu/mips/gs264/mipscfg.c | 79 | ||||
| -rw-r--r-- | libcpu/mips/gs264/mmu.c | 819 | ||||
| -rw-r--r-- | libcpu/mips/gs264/mmu.h | 113 | ||||
| -rw-r--r-- | libcpu/risc-v/SConscript | 13 | ||||
| -rw-r--r-- | libcpu/risc-v/nuclei/cpuport.c | 2 | ||||
| -rw-r--r-- | libcpu/risc-v/t-head/e906/SConscript | 12 | ||||
| -rw-r--r-- | libcpu/risc-v/t-head/e906/context_gcc.S | 323 | ||||
| -rw-r--r-- | libcpu/risc-v/t-head/e906/cpuport.c | 170 | ||||
| -rw-r--r-- | libcpu/risc-v/t-head/e906/cpuport.h | 55 |
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 |
