From fb8c7829a8a861f9837912ecf926899f48349967 Mon Sep 17 00:00:00 2001 From: bigmagic Date: Thu, 16 Apr 2020 16:10:57 +0800 Subject: add raspi4 bsp --- libcpu/aarch64/SConscript | 3 + libcpu/aarch64/common/SConscript | 24 +++ libcpu/aarch64/common/armv8.h | 63 ++++++ libcpu/aarch64/common/cache.S | 151 +++++++++++++ libcpu/aarch64/common/context_gcc.S | 351 ++++++++++++++++++++++++++++++ libcpu/aarch64/common/cp15.h | 166 ++++++++++++++ libcpu/aarch64/common/cpu.c | 91 ++++++++ libcpu/aarch64/common/cpu_gcc.S | 82 +++++++ libcpu/aarch64/common/gic/SConscript | 24 +++ libcpu/aarch64/common/gic/gic_pl400.c | 368 ++++++++++++++++++++++++++++++++ libcpu/aarch64/common/gic/gic_pl400.h | 35 +++ libcpu/aarch64/common/mmu.c | 367 +++++++++++++++++++++++++++++++ libcpu/aarch64/common/mmu.h | 78 +++++++ libcpu/aarch64/common/startup_gcc.S | 13 ++ libcpu/aarch64/common/vector_gcc.S | 61 ++++++ libcpu/aarch64/cortex-a53/SConscript | 15 +- libcpu/aarch64/cortex-a53/armv8.h | 63 ------ libcpu/aarch64/cortex-a53/cache.S | 151 ------------- libcpu/aarch64/cortex-a53/context_gcc.S | 351 ------------------------------ libcpu/aarch64/cortex-a53/cp15.h | 166 -------------- libcpu/aarch64/cortex-a53/cpu.c | 91 -------- libcpu/aarch64/cortex-a53/cpu_gcc.S | 82 ------- libcpu/aarch64/cortex-a53/interrupt.h | 6 +- libcpu/aarch64/cortex-a53/mmu.c | 367 ------------------------------- libcpu/aarch64/cortex-a53/mmu.h | 78 ------- libcpu/aarch64/cortex-a53/startup_gcc.S | 13 -- libcpu/aarch64/cortex-a53/vector_gcc.S | 61 ------ libcpu/aarch64/cortex-a57/SConscript | 13 ++ libcpu/aarch64/cortex-a57/entry_point.S | 111 ++++++++++ libcpu/aarch64/cortex-a57/interrupt.c | 73 +++++++ libcpu/aarch64/cortex-a57/interrupt.h | 27 +++ libcpu/aarch64/cortex-a57/stack.c | 90 ++++++++ libcpu/aarch64/cortex-a57/trap.c | 98 +++++++++ 33 files changed, 2297 insertions(+), 1436 deletions(-) create mode 100644 libcpu/aarch64/common/SConscript create mode 100644 libcpu/aarch64/common/armv8.h create mode 100644 libcpu/aarch64/common/cache.S create mode 100644 libcpu/aarch64/common/context_gcc.S create mode 100644 libcpu/aarch64/common/cp15.h create mode 100644 libcpu/aarch64/common/cpu.c create mode 100644 libcpu/aarch64/common/cpu_gcc.S create mode 100644 libcpu/aarch64/common/gic/SConscript create mode 100644 libcpu/aarch64/common/gic/gic_pl400.c create mode 100644 libcpu/aarch64/common/gic/gic_pl400.h create mode 100644 libcpu/aarch64/common/mmu.c create mode 100644 libcpu/aarch64/common/mmu.h create mode 100644 libcpu/aarch64/common/startup_gcc.S create mode 100644 libcpu/aarch64/common/vector_gcc.S delete mode 100644 libcpu/aarch64/cortex-a53/armv8.h delete mode 100644 libcpu/aarch64/cortex-a53/cache.S delete mode 100644 libcpu/aarch64/cortex-a53/context_gcc.S delete mode 100644 libcpu/aarch64/cortex-a53/cp15.h delete mode 100644 libcpu/aarch64/cortex-a53/cpu.c delete mode 100644 libcpu/aarch64/cortex-a53/cpu_gcc.S delete mode 100644 libcpu/aarch64/cortex-a53/mmu.c delete mode 100644 libcpu/aarch64/cortex-a53/mmu.h delete mode 100644 libcpu/aarch64/cortex-a53/startup_gcc.S delete mode 100644 libcpu/aarch64/cortex-a53/vector_gcc.S create mode 100644 libcpu/aarch64/cortex-a57/SConscript create mode 100644 libcpu/aarch64/cortex-a57/entry_point.S create mode 100644 libcpu/aarch64/cortex-a57/interrupt.c create mode 100644 libcpu/aarch64/cortex-a57/interrupt.h create mode 100644 libcpu/aarch64/cortex-a57/stack.c create mode 100644 libcpu/aarch64/cortex-a57/trap.c (limited to 'libcpu') diff --git a/libcpu/aarch64/SConscript b/libcpu/aarch64/SConscript index 453afe4b3e..5fca2b473b 100644 --- a/libcpu/aarch64/SConscript +++ b/libcpu/aarch64/SConscript @@ -9,6 +9,9 @@ cwd = GetCurrentDir() group = [] list = os.listdir(cwd) +# add common code files +group = group + SConscript(os.path.join('common', 'SConscript')) + # cpu porting code files if rtconfig.CPU != 'common': group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript')) diff --git a/libcpu/aarch64/common/SConscript b/libcpu/aarch64/common/SConscript new file mode 100644 index 0000000000..72fb8e26c3 --- /dev/null +++ b/libcpu/aarch64/common/SConscript @@ -0,0 +1,24 @@ +# RT-Thread building script for component + +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') + Glob('*.S') +CPPPATH = [cwd] + +group = DefineGroup('common', src, depend = [''], CPPPATH = CPPPATH) + +# build for sub-directory +list = os.listdir(cwd) +objs = [] + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) +group = group + objs + + +Return('group') diff --git a/libcpu/aarch64/common/armv8.h b/libcpu/aarch64/common/armv8.h new file mode 100644 index 0000000000..4350890544 --- /dev/null +++ b/libcpu/aarch64/common/armv8.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ + +#ifndef __ARMV8_H__ +#define __ARMV8_H__ + +/* the exception stack without VFP registers */ +struct rt_hw_exp_stack +{ + unsigned long long pc; + unsigned long long spsr; + unsigned long long x30; + unsigned long long xz; + unsigned long long x28; + unsigned long long x29; + unsigned long long x26; + unsigned long long x27; + unsigned long long x24; + unsigned long long x25; + unsigned long long x22; + unsigned long long x23; + unsigned long long x20; + unsigned long long x21; + unsigned long long x18; + unsigned long long x19; + unsigned long long x16; + unsigned long long x17; + unsigned long long x14; + unsigned long long x15; + unsigned long long x12; + unsigned long long x13; + unsigned long long x10; + unsigned long long x11; + unsigned long long x8; + unsigned long long x9; + unsigned long long x6; + unsigned long long x7; + unsigned long long x4; + unsigned long long x5; + unsigned long long x2; + unsigned long long x3; + unsigned long long x0; + unsigned long long x1; +}; + +#define SP_ELx ( ( unsigned long long ) 0x01 ) +#define SP_EL0 ( ( unsigned long long ) 0x00 ) +#define PSTATE_EL1 ( ( unsigned long long ) 0x04 ) +#define PSTATE_EL2 ( ( unsigned long long ) 0x08 ) +#define PSTATE_EL3 ( ( unsigned long long ) 0x0c ) + +rt_ubase_t rt_hw_get_current_el(void); +void rt_hw_set_elx_env(void); +void rt_hw_set_current_vbar(rt_ubase_t addr); + +#endif diff --git a/libcpu/aarch64/common/cache.S b/libcpu/aarch64/common/cache.S new file mode 100644 index 0000000000..7f295a2b02 --- /dev/null +++ b/libcpu/aarch64/common/cache.S @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-03-17 bigmagic first version + */ + +/* + * void __asm_dcache_level(level) + * + * flush or invalidate one level cache. + * + * x0: cache level + * x1: 0 clean & invalidate, 1 invalidate only + * x2~x9: clobbered + */ +.globl __asm_dcache_level +__asm_dcache_level: + lsl x12, x0, #1 + msr csselr_el1, x12 /* select cache level */ + isb /* sync change of cssidr_el1 */ + mrs x6, ccsidr_el1 /* read the new cssidr_el1 */ + and x2, x6, #7 /* x2 <- log2(cache line size)-4 */ + add x2, x2, #4 /* x2 <- log2(cache line size) */ + mov x3, #0x3ff + and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */ + clz w5, w3 /* bit position of #ways */ + mov x4, #0x7fff + and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */ + /* x12 <- cache level << 1 */ + /* x2 <- line length offset */ + /* x3 <- number of cache ways - 1 */ + /* x4 <- number of cache sets - 1 */ + /* x5 <- bit position of #ways */ + +loop_set: + mov x6, x3 /* x6 <- working copy of #ways */ +loop_way: + lsl x7, x6, x5 + orr x9, x12, x7 /* map way and level to cisw value */ + lsl x7, x4, x2 + orr x9, x9, x7 /* map set number to cisw value */ + tbz w1, #0, 1f + dc isw, x9 + b 2f +1: dc cisw, x9 /* clean & invalidate by set/way */ +2: subs x6, x6, #1 /* decrement the way */ + b.ge loop_way + subs x4, x4, #1 /* decrement the set */ + b.ge loop_set + + ret + +/* + * void __asm_flush_dcache_all(int invalidate_only) + * + * x0: 0 clean & invalidate, 1 invalidate only + * + * flush or invalidate all data cache by SET/WAY. + */ +.globl __asm_dcache_all +__asm_dcache_all: + mov x1, x0 + dsb sy + mrs x10, clidr_el1 /* read clidr_el1 */ + lsr x11, x10, #24 + and x11, x11, #0x7 /* x11 <- loc */ + cbz x11, finished /* if loc is 0, exit */ + mov x15, lr + mov x0, #0 /* start flush at cache level 0 */ + /* x0 <- cache level */ + /* x10 <- clidr_el1 */ + /* x11 <- loc */ + /* x15 <- return address */ + +loop_level: + lsl x12, x0, #1 + add x12, x12, x0 /* x0 <- tripled cache level */ + lsr x12, x10, x12 + and x12, x12, #7 /* x12 <- cache type */ + cmp x12, #2 + b.lt skip /* skip if no cache or icache */ + bl __asm_dcache_level /* x1 = 0 flush, 1 invalidate */ +skip: + add x0, x0, #1 /* increment cache level */ + cmp x11, x0 + b.gt loop_level + + mov x0, #0 + msr csselr_el1, x0 /* restore csselr_el1 */ + dsb sy + isb + mov lr, x15 + +finished: + ret + +.globl __asm_flush_dcache_all +__asm_flush_dcache_all: + mov x0, #0 + b __asm_dcache_all + +.globl __asm_invalidate_dcache_all +__asm_invalidate_dcache_all: + mov x0, #0x1 + b __asm_dcache_all + +/* + * void __asm_flush_dcache_range(start, end) + * + * clean & invalidate data cache in the range + * + * x0: start address + * x1: end address + */ +.globl __asm_flush_dcache_range +__asm_flush_dcache_range: + mrs x3, ctr_el0 + lsr x3, x3, #16 + and x3, x3, #0xf + mov x2, #4 + lsl x2, x2, x3 /* cache line size */ + + /* x2 <- minimal cache line size in cache system */ + sub x3, x2, #1 + bic x0, x0, x3 +1: dc civac, x0 /* clean & invalidate data or unified cache */ + add x0, x0, x2 + cmp x0, x1 + b.lo 1b + dsb sy + ret + +/* + * void __asm_invalidate_icache_all(void) + * + * invalidate all tlb entries. + */ +.globl __asm_invalidate_icache_all +__asm_invalidate_icache_all: + ic ialluis + isb sy + ret + +.globl __asm_flush_l3_cache +__asm_flush_l3_cache: + mov x0, #0 /* return status as success */ + ret \ No newline at end of file diff --git a/libcpu/aarch64/common/context_gcc.S b/libcpu/aarch64/common/context_gcc.S new file mode 100644 index 0000000000..934db7ed84 --- /dev/null +++ b/libcpu/aarch64/common/context_gcc.S @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-06 ZhaoXiaowei the first version + */ + + /* + *enable gtimer + */ +.globl rt_hw_gtimer_enable +rt_hw_gtimer_enable: + MOV X0,#1 + MSR CNTP_CTL_EL0,X0 + RET + +/* + *set gtimer CNTP_TVAL_EL0 value + */ +.globl rt_hw_set_gtimer_val +rt_hw_set_gtimer_val: + MSR CNTP_TVAL_EL0,X0 + RET + +/* + *get gtimer CNTP_TVAL_EL0 value + */ +.globl rt_hw_get_gtimer_val +rt_hw_get_gtimer_val: + MRS X0,CNTP_TVAL_EL0 + RET + + +.globl rt_hw_get_cntpct_val +rt_hw_get_cntpct_val: + MRS X0, CNTPCT_EL0 + RET + +/* + *get gtimer frq value + */ +.globl rt_hw_get_gtimer_frq +rt_hw_get_gtimer_frq: + MRS X0,CNTFRQ_EL0 + RET + +.macro SAVE_CONTEXT + + /* Switch to use the EL0 stack pointer. */ + MSR SPSEL, #0 + + /* Save the entire context. */ + STP X0, X1, [SP, #-0x10]! + STP X2, X3, [SP, #-0x10]! + STP X4, X5, [SP, #-0x10]! + STP X6, X7, [SP, #-0x10]! + STP X8, X9, [SP, #-0x10]! + STP X10, X11, [SP, #-0x10]! + STP X12, X13, [SP, #-0x10]! + STP X14, X15, [SP, #-0x10]! + STP X16, X17, [SP, #-0x10]! + STP X18, X19, [SP, #-0x10]! + STP X20, X21, [SP, #-0x10]! + STP X22, X23, [SP, #-0x10]! + STP X24, X25, [SP, #-0x10]! + STP X26, X27, [SP, #-0x10]! + STP X28, X29, [SP, #-0x10]! + STP X30, XZR, [SP, #-0x10]! + + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . +3: + MRS X3, SPSR_EL3 + /* Save the ELR. */ + MRS X2, ELR_EL3 + B 0f +2: + MRS X3, SPSR_EL2 + /* Save the ELR. */ + MRS X2, ELR_EL2 + B 0f +1: + MRS X3, SPSR_EL1 + MRS X2, ELR_EL1 + B 0f +0: + + STP X2, X3, [SP, #-0x10]! + + MOV X0, SP /* Move SP into X0 for saving. */ + + /* Switch to use the ELx stack pointer. */ + MSR SPSEL, #1 + + .endm + +.macro SAVE_CONTEXT_T + + /* Switch to use the EL0 stack pointer. */ + MSR SPSEL, #0 + + /* Save the entire context. */ + STP X0, X1, [SP, #-0x10]! + STP X2, X3, [SP, #-0x10]! + STP X4, X5, [SP, #-0x10]! + STP X6, X7, [SP, #-0x10]! + STP X8, X9, [SP, #-0x10]! + STP X10, X11, [SP, #-0x10]! + STP X12, X13, [SP, #-0x10]! + STP X14, X15, [SP, #-0x10]! + STP X16, X17, [SP, #-0x10]! + STP X18, X19, [SP, #-0x10]! + STP X20, X21, [SP, #-0x10]! + STP X22, X23, [SP, #-0x10]! + STP X24, X25, [SP, #-0x10]! + STP X26, X27, [SP, #-0x10]! + STP X28, X29, [SP, #-0x10]! + STP X30, XZR, [SP, #-0x10]! + + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . +3: + MRS X3, SPSR_EL3 + MOV X2, X30 + B 0f +2: + MRS X3, SPSR_EL2 + MOV X2, X30 + B 0f +1: + MRS X3, SPSR_EL1 + MOV X2, X30 + B 0f +0: + + STP X2, X3, [SP, #-0x10]! + + MOV X0, SP /* Move SP into X0 for saving. */ + + /* Switch to use the ELx stack pointer. */ + MSR SPSEL, #1 + + .endm + +.macro RESTORE_CONTEXT + + /* Switch to use the EL0 stack pointer. */ + MSR SPSEL, #0 + + /* Set the SP to point to the stack of the task being restored. */ + MOV SP, X0 + + LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */ + + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . +3: + MSR SPSR_EL3, X3 + MSR ELR_EL3, X2 + B 0f +2: + MSR SPSR_EL2, X3 + MSR ELR_EL2, X2 + B 0f +1: + MSR SPSR_EL1, X3 + MSR ELR_EL1, X2 + B 0f +0: + + LDP X30, XZR, [SP], #0x10 + LDP X28, X29, [SP], #0x10 + LDP X26, X27, [SP], #0x10 + LDP X24, X25, [SP], #0x10 + LDP X22, X23, [SP], #0x10 + LDP X20, X21, [SP], #0x10 + LDP X18, X19, [SP], #0x10 + LDP X16, X17, [SP], #0x10 + LDP X14, X15, [SP], #0x10 + LDP X12, X13, [SP], #0x10 + LDP X10, X11, [SP], #0x10 + LDP X8, X9, [SP], #0x10 + LDP X6, X7, [SP], #0x10 + LDP X4, X5, [SP], #0x10 + LDP X2, X3, [SP], #0x10 + LDP X0, X1, [SP], #0x10 + + /* Switch to use the ELx stack pointer. _RB_ Might not be required. */ + MSR SPSEL, #1 + + ERET + + .endm + +.text +/* + * rt_base_t rt_hw_interrupt_disable(); + */ +.globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + MRS X0, DAIF + MSR DAIFSet, #3 + DSB SY + RET + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ +.globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + DSB SY + MOV X1, #0xC0 + ANDS X0, X0, X1 + B.NE rt_hw_interrupt_enable_exit + MSR DAIFClr, #3 +rt_hw_interrupt_enable_exit: + RET + +/* + * void rt_hw_context_switch_to(rt_ubase_t to); + * r0 --> to + */ +.globl rt_hw_context_switch_to +rt_hw_context_switch_to: + LDR X0, [X0] + RESTORE_CONTEXT + +.text +/* + * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); + * r0 --> from + * r1 --> to + */ +.globl rt_hw_context_switch +rt_hw_context_switch: + + MOV X8,X0 + MOV X9,X1 + + SAVE_CONTEXT_T + + STR X0, [X8] // store sp in preempted tasks TCB + LDR X0, [X9] // get new task stack pointer + + RESTORE_CONTEXT + +/* + * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to); + */ +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread +.globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + ADR X2, rt_thread_switch_interrupt_flag + LDR X3, [X2] + CMP X3, #1 + B.EQ _reswitch + ADR X4, rt_interrupt_from_thread // set rt_interrupt_from_thread + MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1 + STR X0, [X4] + STR X3, [X2] +_reswitch: + ADR X2, rt_interrupt_to_thread // set rt_interrupt_to_thread + STR X1, [X2] + RET + +.text + +// -- Exception handlers ---------------------------------- + + .align 8 +.globl vector_fiq +vector_fiq: + SAVE_CONTEXT + STP X0, X1, [SP, #-0x10]! + BL rt_hw_trap_fiq + LDP X0, X1, [SP], #0x10 + RESTORE_CONTEXT + +.globl rt_interrupt_enter +.globl rt_interrupt_leave +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread + + +// ------------------------------------------------------------------- + + .align 8 +.globl vector_irq +vector_irq: + SAVE_CONTEXT + STP X0, X1, [SP, #-0x10]! + + BL rt_interrupt_enter + BL rt_hw_trap_irq + BL rt_interrupt_leave + + LDP X0, X1, [SP], #0x10 + + // if rt_thread_switch_interrupt_flag set, jump to + // rt_hw_context_switch_interrupt_do and don't return + ADR X1, rt_thread_switch_interrupt_flag + LDR X2, [X1] + CMP X2, #1 + B.NE vector_irq_exit + + MOV X2, #0 // clear flag + STR X2, [X1] + + ADR X3, rt_interrupt_from_thread + LDR X4, [X3] + STR x0, [X4] // store sp in preempted tasks's TCB + + ADR x3, rt_interrupt_to_thread + LDR X4, [X3] + LDR x0, [X4] // get new task's stack pointer + +vector_irq_exit: + RESTORE_CONTEXT + +// ------------------------------------------------- + + .align 8 + .globl vector_error +vector_error: + SAVE_CONTEXT + BL rt_hw_trap_error + B . diff --git a/libcpu/aarch64/common/cp15.h b/libcpu/aarch64/common/cp15.h new file mode 100644 index 0000000000..f3ffd6f857 --- /dev/null +++ b/libcpu/aarch64/common/cp15.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ + +#ifndef __CP15_H__ +#define __CP15_H__ + +#ifndef __STATIC_FORCEINLINE +#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif + +#define __WFI() __asm__ volatile ("wfi":::"memory") + +#define __WFE() __asm__ volatile ("wfe":::"memory") + +#define __SEV() __asm__ volatile ("sev") + +__STATIC_FORCEINLINE void __ISB(void) +{ + __asm__ volatile ("isb 0xF":::"memory"); +} + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __asm__ volatile ("dsb 0xF":::"memory"); +} + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ + +__STATIC_FORCEINLINE void __DMB(void) +{ + __asm__ volatile ("dmb 0xF":::"memory"); +} + +#ifdef RT_USING_SMP +static inline void send_ipi_msg(int cpu, int ipi_vector) +{ + IPI_MAILBOX_SET(cpu) = 1 << ipi_vector; +} + +static inline void setup_bootstrap_addr(int cpu, int addr) +{ + CORE_MAILBOX3_SET(cpu) = addr; +} + +static inline void enable_cpu_ipi_intr(int cpu) +{ + COREMB_INTCTL(cpu) = IPI_MAILBOX_INT_MASK; +} + +static inline void enable_cpu_timer_intr(int cpu) +{ + CORETIMER_INTCTL(cpu) = 0x8; +} + +static inline void enable_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 1; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL +} + +static inline void disable_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 0; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL +} + +static inline void mask_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 2; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL +} + +static inline void unmask_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 1; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL +} + +static inline rt_uint64_t read_cntvct(void) +{ + rt_uint32_t val,val1; + asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (val),"=r" (val1)); + return (val); +} + +static inline rt_uint64_t read_cntvoff(void) +{ + + rt_uint64_t val; + asm volatile("mrrc p15, 4, %Q0, %R0, c14" : "=r" (val)); + return (val); +} + +static inline rt_uint32_t read_cntv_tval(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c3, 0" : "=r"(val) ); + return val; +} + + +static inline void write_cntv_tval(rt_uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c14, c3, 0" :: "r"(val) ); + return; +} + +static inline rt_uint32_t read_cntfrq(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val) ); + return val; +} + + +static inline rt_uint32_t read_cntctrl(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c1, 0" : "=r"(val) ); + return val; +} + +static inline uint32_t write_cntctrl(uint32_t val) +{ + + asm volatile ("mcr p15, 0, %0, c14, c1, 0" : :"r"(val) ); + return val; +} +#endif + +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(rt_ubase_t addr); +void rt_hw_mmu_init(void); +void rt_hw_vector_init(void); + +void set_timer_counter(unsigned int counter); +void set_timer_control(unsigned int control); +#endif diff --git a/libcpu/aarch64/common/cpu.c b/libcpu/aarch64/common/cpu.c new file mode 100644 index 0000000000..962a53a071 --- /dev/null +++ b/libcpu/aarch64/common/cpu.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + * 2019-07-28 zdzn add smp support + */ + +#include +#include +#include +#include "cp15.h" + +int rt_hw_cpu_id(void) +{ + int cpu_id; + rt_base_t value; + + __asm__ volatile ( + "mrs %0, mpidr_el1" + :"=r"(value) + ); + cpu_id = value & 0xf; + return cpu_id; +}; + +#ifdef RT_USING_SMP +void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock) +{ + lock->slock = 0; +} + +void rt_hw_spin_lock(rt_hw_spinlock_t *lock) +{ + unsigned long tmp; + unsigned long newval; + rt_hw_spinlock_t lockval; + __asm__ __volatile__( + "pld [%0]" + ::"r"(&lock->slock) + ); + + __asm__ __volatile__( + "1: ldrex %0, [%3]\n" + " add %1, %0, %4\n" + " strex %2, %1, [%3]\n" + " teq %2, #0\n" + " bne 1b" + : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) + : "r" (&lock->slock), "I" (1 << 16) + : "cc"); + + while (lockval.tickets.next != lockval.tickets.owner) { + __WFE(); + lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner); + } + + __DMB(); +} + +void rt_hw_spin_unlock(rt_hw_spinlock_t *lock) +{ + __DMB(); + lock->tickets.owner++; + __DSB(); + __SEV(); +} +#endif /*RT_USING_SMP*/ + +/** + * @addtogroup ARM CPU + */ +/*@{*/ + +/** 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/aarch64/common/cpu_gcc.S b/libcpu/aarch64/common/cpu_gcc.S new file mode 100644 index 0000000000..b8c8b8768c --- /dev/null +++ b/libcpu/aarch64/common/cpu_gcc.S @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Date Author Notes + * 2018-10-06 ZhaoXiaowei the first version + */ + +.text +.globl rt_hw_get_current_el +rt_hw_get_current_el: + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + + LDR X0, =0 + B 0f +3: + LDR X0, =3 + B 0f +2: + LDR X0, =2 + B 0f +1: + LDR X0, =1 + B 0f +0: + RET + + +.globl rt_hw_set_current_vbar +rt_hw_set_current_vbar: + MRS X1, CurrentEL + CMP X1, 0xc + B.EQ 3f + CMP X1, 0x8 + B.EQ 2f + CMP X1, 0x4 + B.EQ 1f + B 0f +3: + MSR VBAR_EL3,X0 + B 0f +2: + MSR VBAR_EL2,X0 + B 0f +1: + MSR VBAR_EL1,X0 + B 0f +0: + RET + + +.globl rt_hw_set_elx_env +rt_hw_set_elx_env: + MRS X1, CurrentEL + CMP X1, 0xc + B.EQ 3f + CMP X1, 0x8 + B.EQ 2f + CMP X1, 0x4 + B.EQ 1f + B 0f +3: + MRS X0, SCR_EL3 + ORR X0, X0, #0xF /* SCR_EL3.NS|IRQ|FIQ|EA */ + MSR SCR_EL3, X0 + B 0f +2: + MRS X0, HCR_EL2 + ORR X0, X0, #0x38 + MSR HCR_EL2, X0 + B 0f +1: + B 0f +0: + RET diff --git a/libcpu/aarch64/common/gic/SConscript b/libcpu/aarch64/common/gic/SConscript new file mode 100644 index 0000000000..b114ba7678 --- /dev/null +++ b/libcpu/aarch64/common/gic/SConscript @@ -0,0 +1,24 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +CPPPATH = [cwd] + +gic400_group = Split(''' +gic_pl400.c +''') + +gic500_group = Split(''' +gic_pl500.c +''') + +src = () +if GetDepend('BSP_USING_GIC400'): + src = gic400_group +if GetDepend('BSP_USING_GIC500'): + src = gic500_group + +group = DefineGroup('gic', src, depend = ['BSP_USING_GIC'], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/aarch64/common/gic/gic_pl400.c b/libcpu/aarch64/common/gic/gic_pl400.c new file mode 100644 index 0000000000..eb35c5b2a4 --- /dev/null +++ b/libcpu/aarch64/common/gic/gic_pl400.c @@ -0,0 +1,368 @@ +/* + * Copyright 2014, General Dynamics C4 Systems + * + * This software may be distributed and modified according to the terms of + * the GNU General Public License version 2. Note that NO WARRANTY is provided. + * See "LICENSE_GPLv2.txt" for details. + * + * @TAG(GD_GPL) + */ + +#include "gic_pl400.h" +#include "iomap.h" + +#define BIT(n) (1ul<<(n)) +#define MASK(n) (BIT(n)-1ul) + +/* Setters/getters helpers */ +#define IRQ_REG(IRQ) ((IRQ) / 32) +#define IRQ_BIT(IRQ) BIT((IRQ) % 32) +#define IRQ_MASK MASK(10) +#define IS_IRQ_VALID(X) (((X)&IRQ_MASK) < SPECIAL_IRQ_START) + +#define CPU(X) (1<<(X)) +#define TARGET_CPU_ALLINT(CPU) ( \ + ( ((CPU)&0xff)<<0 ) |\ + ( ((CPU)&0xff)<<8 ) |\ + ( ((CPU)&0xff)<<16 ) |\ + ( ((CPU)&0xff)<<24 ) \ + ) +#define TARGET_CPU0_ALLINT TARGET_CPU_ALLINT(CPU(0)) + + +#define IRQ_SET_ALL 0xffffffff; + +/* Special IRQ's */ +#define SPECIAL_IRQ_START 1020 +#define IRQ_NONE 1023 + +/* Memory map for GIC distributor */ +struct gic_dist_map { + uint32_t enable; /* 0x000 */ + uint32_t ic_type; /* 0x004 */ + uint32_t dist_ident; /* 0x008 */ + uint32_t res1[29]; /* [0x00C, 0x080) */ + + uint32_t group[32]; /* [0x080, 0x100) */ + + uint32_t enable_set[32]; /* [0x100, 0x180) */ + uint32_t enable_clr[32]; /* [0x180, 0x200) */ + uint32_t pending_set[32]; /* [0x200, 0x280) */ + uint32_t pending_clr[32]; /* [0x280, 0x300) */ + uint32_t active[32]; /* [0x300, 0x380) */ + uint32_t active_clr[32]; /* [0x380, 0x400) */ + + uint32_t priority[255]; /* [0x400, 0x7FC) */ + uint32_t res2; /* 0x7FC */ + + uint32_t targets[255]; /* [0x800, 0xBFC) */ + uint32_t res3; /* 0xBFC */ + + uint32_t config[64]; /* [0xC00, 0xD00) */ + + uint32_t ppi_status; /* [0xD00, 0xD04) */ + uint32_t spi_status[15]; /* [0xD04, 0xD40) */ + uint32_t res4[112]; /* [0xD40, 0xF00) */ + + uint32_t sgi_control; /* 0xF00 */ + uint32_t res5[3]; /* [0xF04, 0xF10) */ + uint32_t sgi_pending_clr[4]; /* [0xF10, 0xF20) */ + uint32_t sgi_pending_set[4]; /* [0xF20, 0xF30) */ + uint32_t res10[40]; /* [0xF30, 0xFD0) */ + + uint32_t periph_id[8]; /* [0xFD0, 0xFF0) */ + uint32_t component_id[4]; /* [0xFF0, 0xFFF] */ +}; + + +/* Memory map for GIC cpu interface */ +struct gic_cpu_iface_map { + uint32_t icontrol; /* 0x000 */ + uint32_t pri_msk_c; /* 0x004 */ + uint32_t bp_c; /* 0x008 */ + uint32_t int_ack; /* 0x00C */ + uint32_t eoi; /* 0x010 */ + uint32_t run_priority; /* 0x014 */ + uint32_t hi_pend; /* 0x018 */ + uint32_t ns_alias_bp_c; /* 0x01C */ + uint32_t ns_alias_ack; /* 0x020 GIC_PL400 only */ + uint32_t ns_alias_eoi; /* 0x024 GIC_PL400 only */ + uint32_t ns_alias_hi_pend; /* 0x028 GIC_PL400 only */ + + uint32_t res1[41]; /* [0x02C, 0x0D0) */ + uint32_t active_priority[4]; /* [0x0D0, 0xC0] GIC_PL400 only */ + uint32_t ns_active_priority[4]; /* [0xE0,0xF0] GIC_PL400 only */ + uint32_t res4[3]; /* [0xF0, 0xFC] */ + + uint32_t cpu_if_ident; /* 0x0FC */ + uint32_t deactive; /* [0x1000] */ +}; + +volatile struct gic_dist_map *gic_dist = + (volatile struct gic_dist_map*)(GIC_PL400_DISTRIBUTOR_PPTR); + +volatile struct gic_cpu_iface_map *gic_cpuiface = + (volatile struct gic_cpu_iface_map*)(GIC_PL400_CONTROLLER_PPTR); + +/* Helpers */ +static inline int +is_irq_pending(irq_t irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + return !!(gic_dist->pending_set[word] & BIT(bit)); +} + +static inline int +is_irq_active(irq_t irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + return !!(gic_dist->active[word] & BIT(bit)); +} + +static inline int +is_irq_enabled(irq_t irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + return !!(gic_dist->enable_set[word] & BIT(bit)); +} + +static inline int +is_irq_edge_triggered(irq_t irq) +{ + int word = irq / 16; + int bit = ((irq & 0xf) * 2); + return !!(gic_dist->config[word] & BIT(bit + 1)); +} + +static inline int +is_irq_1_N(irq_t irq) +{ + int word = irq / 16; + int bit = ((irq & 0xf) * 2); + return !!(gic_dist->config[word] & BIT(bit + 0)); +} + +static inline int +is_irq_N_N(irq_t irq) +{ + return !(is_irq_1_N(irq)); +} + +static inline void +dist_pending_clr(irq_t irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + /* Using |= here is detrimental to your health */ + gic_dist->pending_clr[word] = BIT(bit); +} + +static inline void +dist_pending_set(irq_t irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + gic_dist->pending_set[word] = BIT(bit); +} + +static inline void +dist_enable_clr(irq_t irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + /* Using |= here is detrimental to your health */ + gic_dist->enable_clr[word] = BIT(bit); +} + +static inline void +dist_enable_set(irq_t irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + gic_dist->enable_set[word] = BIT(bit); +} + +/** + DONT_TRANSLATE + */ +static void dist_init(void) +{ + int i; + int nirqs = 32 * ((gic_dist->ic_type & 0x1f) + 1); + gic_dist->enable = 0; + +#if 0 + /* configure to group 0 for security */ + for (i = 0; i < nirqs; i += 32) { + gic_dist->group[i / 32] = 0xffffffff; + } +#endif + + for (i = 0; i < nirqs; i += 32) { + /* disable */ + gic_dist->enable_clr[i / 32] = IRQ_SET_ALL; + /* clear pending */ + gic_dist->pending_clr[i / 32] = IRQ_SET_ALL; + } + + /* reset interrupts priority */ + for (i = 32; i < nirqs; i += 4) { + gic_dist->priority[i / 4] = 0x0; + } + + /* + * reset int target to cpu 0 + * (Should really query which processor we're running on and use that) + */ + for (i = 0; i < nirqs; i += 4) { + gic_dist->targets[i / 4] = TARGET_CPU0_ALLINT; + } + + /* level-triggered, 1-N */ + for (i = 64; i < nirqs; i += 32) { + gic_dist->config[i / 32] = 0; + //gic_dist->config[i / 32] = 0x55555555; + } + /* enable the int controller */ + gic_dist->enable = 1; +} + +/** + DONT_TRANSLATE + */ +static void cpu_iface_init(void) +{ + uint32_t i; + + /* For non-Exynos4, the registers are banked per CPU, need to clear them */ + gic_dist->enable_clr[0] = IRQ_SET_ALL; + gic_dist->pending_clr[0] = IRQ_SET_ALL; + gic_dist->priority[0] = 0x00; + /* put everything in group 0 */ + + /* clear any software generated interrupts */ + for (i = 0; i < 16; i += 4) { + gic_dist->sgi_pending_clr[i / 4] = IRQ_SET_ALL; + } + + gic_cpuiface->icontrol = 0; + gic_cpuiface->pri_msk_c = 0x000000f0; + gic_cpuiface->bp_c = 0x00000003; + + while (((i = gic_cpuiface->int_ack) & IRQ_MASK) != IRQ_NONE) { + gic_cpuiface->eoi = i; + } + gic_cpuiface->icontrol = 0x1; +} + +/** + DONT_TRANSLATE + */ +void initIRQController(void) +{ + dist_init(); + cpu_iface_init(); +} + + + +/* + * The only sane way to get an GIC IRQ number that can be properly + * ACKED later is through the int_ack register. Unfortunately, reading + * this register changes the interrupt state to pending so future + * reads will not return the same value For this reason, we have a + * global variable to store the IRQ number. + */ +static uint32_t active_irq = IRQ_NONE; + +/** + DONT_TRANSLATE + */ +interrupt_t +getActiveIRQ(void) +{ + uint32_t irq; + if (!IS_IRQ_VALID(active_irq)) { + active_irq = gic_cpuiface->int_ack; + } + + if (IS_IRQ_VALID(active_irq)) { + irq = active_irq & IRQ_MASK; + } else { + irq = 1023; + } + + return irq; +} + +/* + * GIC has 4 states: pending->active(+pending)->inactive + * seL4 expects two states: active->inactive. + * We ignore the active state in GIC to conform + */ +/** + DONT_TRANSLATE + */ +bool_t +isIRQPending(void) +{ + return IS_IRQ_VALID(gic_cpuiface->hi_pend); +} + + +/** + DONT_TRANSLATE + */ +void +maskInterrupt(bool_t disable, interrupt_t irq) +{ + if (disable) { + dist_enable_clr(irq); + } else { + dist_enable_set(irq); + } +} + +/** + DONT_TRANSLATE + */ +void +ackInterrupt(irq_t irq) +{ + if (!(IS_IRQ_VALID(active_irq) && (active_irq & IRQ_MASK) == irq)) { + return; + } + if (is_irq_edge_triggered(irq)) { + dist_pending_clr(irq); + } + gic_cpuiface->eoi = active_irq; + active_irq = IRQ_NONE; +} + +void +handleSpuriousIRQ(void) +{ +} + +void rt_hw_interrupt_mask(int vector) +{ + maskInterrupt(1, vector); +} + +void rt_hw_interrupt_umask(int vector) +{ + maskInterrupt(0, vector); +} + +int rt_hw_interrupt_get_irq(void) +{ + return getActiveIRQ(); +} + +void rt_hw_interrupt_ack(int fiq_irq) +{ + return ackInterrupt(fiq_irq); +} diff --git a/libcpu/aarch64/common/gic/gic_pl400.h b/libcpu/aarch64/common/gic/gic_pl400.h new file mode 100644 index 0000000000..a43583bd7c --- /dev/null +++ b/libcpu/aarch64/common/gic/gic_pl400.h @@ -0,0 +1,35 @@ + +#ifndef __ARCH_MACHINE_GIC_PL400_H +#define __ARCH_MACHINE_GIC_PL400_H + +#include + +typedef uint16_t interrupt_t; +typedef uint16_t irq_t; +typedef uint64_t bool_t; + +/** MODIFIES: [*] */ +interrupt_t getActiveIRQ(void); +/** MODIFIES: [*] */ +interrupt_t getPendingIRQ(void); +/** MODIFIES: [*] */ +bool_t isIRQPending(void); +/** MODIFIES: [*] */ +void maskInterrupt(bool_t disable, interrupt_t irq); +/** MODIFIES: [*] */ +void ackInterrupt(irq_t irq); +/** MODIFIES: [*] */ +static inline void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow) { } + +/** MODIFIES: [*] */ +void initIRQController(void); + +void handleSpuriousIRQ(void); + +void rt_hw_interrupt_umask(int vector); + +int rt_hw_interrupt_get_irq(void); + +void rt_hw_interrupt_ack(int fiq_irq); +#endif /* !__ARCH_MACHINE_GIC400_H */ + diff --git a/libcpu/aarch64/common/mmu.c b/libcpu/aarch64/common/mmu.c new file mode 100644 index 0000000000..b799143084 --- /dev/null +++ b/libcpu/aarch64/common/mmu.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-02-20 bigmagic first version + */ +#include +#include +#include + +#define TTBR_CNP 1 + +typedef unsigned long int uint64_t; + +static unsigned long main_tbl[512 * 20] __attribute__((aligned (4096))); + +#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) + +#define PMD_TYPE_SECT (1 << 0) + +#define PMD_TYPE_TABLE (3 << 0) + +#define PTE_TYPE_PAGE (3 << 0) + +#define BITS_PER_VA 39 + +/* Granule size of 4KB is being used */ +#define GRANULE_SIZE_SHIFT 12 +#define GRANULE_SIZE (1 << GRANULE_SIZE_SHIFT) +#define XLAT_ADDR_MASK ((1UL << BITS_PER_VA) - GRANULE_SIZE) + +#define PMD_TYPE_MASK (3 << 0) + +int free_idx = 1; + +void __asm_invalidate_icache_all(void); +void __asm_flush_dcache_all(void); +int __asm_flush_l3_cache(void); +void __asm_flush_dcache_range(unsigned long long start, unsigned long long end); +void __asm_invalidate_dcache_all(void); +void __asm_invalidate_icache_all(void); + +void mmu_memset(char *dst, char v, size_t len) +{ + while (len--) + { + *dst++ = v; + } +} + +static unsigned long __page_off = 0; +static unsigned long get_free_page(void) +{ + __page_off += 512; + return (unsigned long)(main_tbl + __page_off); +} + + +static inline unsigned int get_sctlr(void) +{ + unsigned int val; + asm volatile("mrs %0, sctlr_el1" : "=r" (val) : : "cc"); + return val; +} + +static inline void set_sctlr(unsigned int val) +{ + asm volatile("msr sctlr_el1, %0" : : "r" (val) : "cc"); + asm volatile("isb"); +} + +void mmu_init(void) +{ + unsigned long val64; + unsigned long val32; + + val64 = 0x007f6eUL; + __asm__ volatile("msr MAIR_EL1, %0\n dsb sy\n"::"r"(val64)); + __asm__ volatile("mrs %0, MAIR_EL1\n dsb sy\n":"=r"(val64)); + + //TCR_EL1 + val32 = (16UL << 0)//48bit + | (0x0UL << 6) + | (0x0UL << 7) + | (0x3UL << 8) + | (0x3UL << 10)//Inner Shareable + | (0x2UL << 12) + | (0x0UL << 14)//4K + | (0x0UL << 16) + | (0x0UL << 22) + | (0x1UL << 23) + | (0x2UL << 30) + | (0x1UL << 32) + | (0x0UL << 35) + | (0x0UL << 36) + | (0x0UL << 37) + | (0x0UL << 38); + __asm__ volatile("msr TCR_EL1, %0\n"::"r"(val32)); + __asm__ volatile("mrs %0, TCR_EL1\n":"=r"(val32)); + + __asm__ volatile("msr TTBR0_EL1, %0\n dsb sy\n"::"r"(main_tbl)); + __asm__ volatile("mrs %0, TTBR0_EL1\n dsb sy\n":"=r"(val64)); + + mmu_memset((char *)main_tbl, 0, 4096); +} + +void mmu_enable(void) +{ + unsigned long val64; + unsigned long val32; + + __asm__ volatile("mrs %0, SCTLR_EL1\n":"=r"(val64)); + val64 &= ~0x1000; //disable I + __asm__ volatile("dmb sy\n msr SCTLR_EL1, %0\n isb sy\n"::"r"(val64)); + + __asm__ volatile("IC IALLUIS\n dsb sy\n isb sy\n"); + __asm__ volatile("tlbi vmalle1\n dsb sy\n isb sy\n"); + + //SCTLR_EL1, turn on mmu + __asm__ volatile("mrs %0, SCTLR_EL1\n":"=r"(val32)); + val32 |= 0x1005; //enable mmu, I C M + __asm__ volatile("dmb sy\n msr SCTLR_EL1, %0\nisb sy\n"::"r"(val32)); + rt_hw_icache_enable(); + rt_hw_dcache_enable(); + +} + +static int map_single_page_2M(unsigned long* lv0_tbl, unsigned long va, unsigned long pa, unsigned long attr) +{ + int level; + unsigned long* cur_lv_tbl = lv0_tbl; + unsigned long page; + unsigned long off; + int level_shift = 39; + + if (va & (0x200000UL - 1)) + { + return MMU_MAP_ERROR_VANOTALIGN; + } + if (pa & (0x200000UL - 1)) + { + return MMU_MAP_ERROR_PANOTALIGN; + } + for (level = 0; level < 2; level++) + { + off = (va >> level_shift); + off &= MMU_LEVEL_MASK; + if ((cur_lv_tbl[off] & 1) == 0) + { + page = get_free_page(); + if (!page) + { + return MMU_MAP_ERROR_NOPAGE; + } + mmu_memset((char *)page, 0, 4096); + cur_lv_tbl[off] = page | 0x3UL; + } + page = cur_lv_tbl[off]; + if (!(page & 0x2)) + { + //is block! error! + return MMU_MAP_ERROR_CONFLICT; + } + cur_lv_tbl = (unsigned long*)(page & 0x0000fffffffff000UL); + level_shift -= 9; + } + attr &= 0xfff0000000000ffcUL; + pa |= (attr | 0x1UL); //block + off = (va >> 21); + off &= MMU_LEVEL_MASK; + cur_lv_tbl[off] = pa; + return 0; +} + +int armv8_map_2M(unsigned long va, unsigned long pa, int count, unsigned long attr) +{ + int i; + int ret; + + if (va & (0x200000 - 1)) + { + return -1; + } + if (pa & (0x200000 - 1)) + { + return -1; + } + for (i = 0; i < count; i++) + { + ret = map_single_page_2M((unsigned long *)main_tbl, va, pa, attr); + va += 0x200000; + pa += 0x200000; + if (ret != 0) + { + return ret; + } + } + return 0; +} + +static void set_table(uint64_t *pt, uint64_t *table_addr) +{ + uint64_t val; + val = (0x3UL | (uint64_t)table_addr); + *pt = val; +} + +void mmu_memset2(unsigned char *dst, char v, int len) +{ + while (len--) + { + *dst++ = v; + } +} + +static uint64_t *create_table(void) +{ + uint64_t *new_table = (uint64_t *)((unsigned char *)&main_tbl[0] + free_idx * 4096); //+ free_idx * GRANULE_SIZE; + /* Mark all entries as invalid */ + mmu_memset2((unsigned char *)new_table, 0, 4096); + free_idx++; + return new_table; +} + +static int pte_type(uint64_t *pte) +{ + return *pte & PMD_TYPE_MASK; +} + +static int level2shift(int level) +{ + /* Page is 12 bits wide, every level translates 9 bits */ + return (12 + 9 * (3 - level)); +} + +static uint64_t *get_level_table(uint64_t *pte) +{ + uint64_t *table = (uint64_t *)(*pte & XLAT_ADDR_MASK); + + if (pte_type(pte) != PMD_TYPE_TABLE) + { + table = create_table(); + set_table(pte, table); + } + return table; +} + +static void map_region(uint64_t virt, uint64_t phys, uint64_t size, uint64_t attr) +{ + uint64_t block_size = 0; + uint64_t block_shift = 0; + uint64_t *pte; + uint64_t idx = 0; + uint64_t addr = 0; + uint64_t *table = 0; + int level = 0; + + addr = virt; + while (size) + { + table = &main_tbl[0]; + for (level = 0; level < 4; level++) + { + block_shift = level2shift(level); + idx = addr >> block_shift; + idx = idx%512; + block_size = (uint64_t)(1L << block_shift); + pte = table + idx; + + if (size >= block_size && IS_ALIGNED(addr, block_size)) + { + attr &= 0xfff0000000000ffcUL; + if(level != 3) + { + *pte = phys | (attr | 0x1UL); + } + else + { + *pte = phys | (attr | 0x3UL); + } + addr += block_size; + phys += block_size; + size -= block_size; + break; + } + table = get_level_table(pte); + } + } +} + +void armv8_map(unsigned long va, unsigned long pa, unsigned long size, unsigned long attr) +{ + map_region(va, pa, size, attr); +} + +void rt_hw_dcache_enable(void) +{ + if (!(get_sctlr() & CR_M)) + { + rt_kprintf("please init mmu!\n"); + } + else + { + set_sctlr(get_sctlr() | CR_C); + } +} + +void rt_hw_dcache_flush_all(void) +{ + int ret; + + __asm_flush_dcache_all(); + ret = __asm_flush_l3_cache(); + if (ret) + { + rt_kprintf("flushing dcache returns 0x%x\n", ret); + } + else + { + rt_kprintf("flushing dcache successfully.\n"); + } +} + +void rt_hw_dcache_flush_range(unsigned long start_addr, unsigned long size) +{ + __asm_flush_dcache_range(start_addr, start_addr + size); +} +void rt_hw_dcache_invalidate_range(unsigned long start_addr,unsigned long size) +{ + __asm_flush_dcache_range(start_addr, start_addr + size); +} + +void rt_hw_dcache_invalidate_all(void) +{ + __asm_invalidate_dcache_all(); +} + +void rt_hw_dcache_disable(void) +{ + /* if cache isn't enabled no need to disable */ + if(!(get_sctlr() & CR_C)) + { + rt_kprintf("need enable cache!\n"); + return; + } + set_sctlr(get_sctlr() & ~CR_C); +} + +//icache +void rt_hw_icache_enable(void) +{ + __asm_invalidate_icache_all(); + set_sctlr(get_sctlr() | CR_I); +} + +void rt_hw_icache_invalidate_all(void) +{ + __asm_invalidate_icache_all(); +} + +void rt_hw_icache_disable(void) +{ + set_sctlr(get_sctlr() & ~CR_I); +} \ No newline at end of file diff --git a/libcpu/aarch64/common/mmu.h b/libcpu/aarch64/common/mmu.h new file mode 100644 index 0000000000..6a66472c79 --- /dev/null +++ b/libcpu/aarch64/common/mmu.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-02-20 bigmagic first version + */ + +#ifndef __MMU_H__ +#define __MMU_H__ + +/* + * CR1 bits (CP#15 CR1) + */ +#define CR_M (1 << 0) /* MMU enable */ +#define CR_A (1 << 1) /* Alignment abort enable */ +#define CR_C (1 << 2) /* Dcache enable */ +#define CR_W (1 << 3) /* Write buffer enable */ +#define CR_P (1 << 4) /* 32-bit exception handler */ +#define CR_D (1 << 5) /* 32-bit data address range */ +#define CR_L (1 << 6) /* Implementation defined */ +#define CR_B (1 << 7) /* Big endian */ +#define CR_S (1 << 8) /* System MMU protection */ +#define CR_R (1 << 9) /* ROM MMU protection */ +#define CR_F (1 << 10) /* Implementation defined */ +#define CR_Z (1 << 11) /* Implementation defined */ +#define CR_I (1 << 12) /* Icache enable */ +#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */ +#define CR_RR (1 << 14) /* Round Robin cache replacement */ +#define CR_L4 (1 << 15) /* LDR pc can set T bit */ +#define CR_DT (1 << 16) +#define CR_IT (1 << 18) +#define CR_ST (1 << 19) +#define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */ +#define CR_U (1 << 22) /* Unaligned access operation */ +#define CR_XP (1 << 23) /* Extended page tables */ +#define CR_VE (1 << 24) /* Vectored interrupts */ +#define CR_EE (1 << 25) /* Exception (Big) Endian */ +#define CR_TRE (1 << 28) /* TEX remap enable */ +#define CR_AFE (1 << 29) /* Access flag enable */ +#define CR_TE (1 << 30) /* Thumb exception enable */ + +#define MMU_LEVEL_MASK 0x1ffUL +#define MMU_MAP_ERROR_VANOTALIGN -1 +#define MMU_MAP_ERROR_PANOTALIGN -2 +#define MMU_MAP_ERROR_NOPAGE -3 +#define MMU_MAP_ERROR_CONFLICT -4 + +#define MEM_ATTR_MEMORY ((0x1UL << 10) | (0x2UL << 8) | (0x0UL << 6) | (0x1UL << 2)) +#define MEM_ATTR_IO ((0x1UL << 10) | (0x2UL << 8) | (0x0UL << 6) | (0x2UL << 2)) + +#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000) + +void mmu_init(void); + +void mmu_enable(void); + +int armv8_map_2M(unsigned long va, unsigned long pa, int count, unsigned long attr); + +void armv8_map(unsigned long va, unsigned long pa, unsigned long size, unsigned long attr); + +//dcache +void rt_hw_dcache_enable(void); +void rt_hw_dcache_flush_all(void); +void rt_hw_dcache_flush_range(unsigned long start_addr, unsigned long size); +void rt_hw_dcache_invalidate_range(unsigned long start_addr,unsigned long size); +void rt_hw_dcache_invalidate_all(void); +void rt_hw_dcache_disable(void); + +//icache +void rt_hw_icache_enable(void); +void rt_hw_icache_invalidate_all(void); +void rt_hw_icache_disable(void); + + +#endif /*__MMU_H__*/ diff --git a/libcpu/aarch64/common/startup_gcc.S b/libcpu/aarch64/common/startup_gcc.S new file mode 100644 index 0000000000..ea4268148c --- /dev/null +++ b/libcpu/aarch64/common/startup_gcc.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + + .global Reset_Handler + .section ".start", "ax" +Reset_Handler: + nop diff --git a/libcpu/aarch64/common/vector_gcc.S b/libcpu/aarch64/common/vector_gcc.S new file mode 100644 index 0000000000..fc88cce7f8 --- /dev/null +++ b/libcpu/aarch64/common/vector_gcc.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Date Author Notes + * 2018-10-06 ZhaoXiaowei the first version + */ + +.text + +.globl system_vectors +.globl vector_error +.globl vector_irq +.globl vector_fiq + +system_vectors: +.align 11 + .set VBAR, system_vectors + .org VBAR + // Exception from CurrentEL (EL1) with SP_EL0 (SPSEL=1) + .org (VBAR + 0x00 + 0) + B vector_error // Synchronous + .org (VBAR + 0x80 + 0) + B vector_irq // IRQ/vIRQ + .org (VBAR + 0x100 + 0) + B vector_fiq // FIQ/vFIQ + .org (VBAR + 0x180 + 0) + B vector_error // Error/vError + + // Exception from CurrentEL (EL1) with SP_ELn + .org (VBAR + 0x200 + 0) + B vector_error // Synchronous + .org (VBAR + 0x280 + 0) + B vector_irq // IRQ/vIRQ + .org (VBAR + 0x300 + 0) + B vector_fiq // FIQ/vFIQ + .org (VBAR + 0x380 + 0) + B vector_error + + // Exception from lower EL, aarch64 + .org (VBAR + 0x400 + 0) + B vector_error + .org (VBAR + 0x480 + 0) + B vector_error + .org (VBAR + 0x500 + 0) + B vector_error + .org (VBAR + 0x580 + 0) + B vector_error + + // Exception from lower EL, aarch32 + .org (VBAR + 0x600 + 0) + B vector_error + .org (VBAR + 0x680 + 0) + B vector_error + .org (VBAR + 0x700 + 0) + B vector_error + .org (VBAR + 0x780 + 0) + B vector_error + .org (VBAR + 0x800 + 0) + B vector_error diff --git a/libcpu/aarch64/cortex-a53/SConscript b/libcpu/aarch64/cortex-a53/SConscript index 75e170a0cf..c6a4817802 100644 --- a/libcpu/aarch64/cortex-a53/SConscript +++ b/libcpu/aarch64/cortex-a53/SConscript @@ -1,16 +1,13 @@ +# RT-Thread building script for component + from building import * +Import('rtconfig') + cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') -asm_src = Split(''' -context_gcc.S -vector_gcc.S -entry_point.S -cpu_gcc.S -cache.S -''') +src = Glob('*.c') + Glob('*.cpp') + Glob('*.S') CPPPATH = [cwd] -group = DefineGroup('cpu', src + asm_src, depend = [''], CPPPATH = CPPPATH) +group = DefineGroup('common', src, depend = [''], CPPPATH = CPPPATH) Return('group') diff --git a/libcpu/aarch64/cortex-a53/armv8.h b/libcpu/aarch64/cortex-a53/armv8.h deleted file mode 100644 index 4350890544..0000000000 --- a/libcpu/aarch64/cortex-a53/armv8.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-09-15 Bernard first version - */ - -#ifndef __ARMV8_H__ -#define __ARMV8_H__ - -/* the exception stack without VFP registers */ -struct rt_hw_exp_stack -{ - unsigned long long pc; - unsigned long long spsr; - unsigned long long x30; - unsigned long long xz; - unsigned long long x28; - unsigned long long x29; - unsigned long long x26; - unsigned long long x27; - unsigned long long x24; - unsigned long long x25; - unsigned long long x22; - unsigned long long x23; - unsigned long long x20; - unsigned long long x21; - unsigned long long x18; - unsigned long long x19; - unsigned long long x16; - unsigned long long x17; - unsigned long long x14; - unsigned long long x15; - unsigned long long x12; - unsigned long long x13; - unsigned long long x10; - unsigned long long x11; - unsigned long long x8; - unsigned long long x9; - unsigned long long x6; - unsigned long long x7; - unsigned long long x4; - unsigned long long x5; - unsigned long long x2; - unsigned long long x3; - unsigned long long x0; - unsigned long long x1; -}; - -#define SP_ELx ( ( unsigned long long ) 0x01 ) -#define SP_EL0 ( ( unsigned long long ) 0x00 ) -#define PSTATE_EL1 ( ( unsigned long long ) 0x04 ) -#define PSTATE_EL2 ( ( unsigned long long ) 0x08 ) -#define PSTATE_EL3 ( ( unsigned long long ) 0x0c ) - -rt_ubase_t rt_hw_get_current_el(void); -void rt_hw_set_elx_env(void); -void rt_hw_set_current_vbar(rt_ubase_t addr); - -#endif diff --git a/libcpu/aarch64/cortex-a53/cache.S b/libcpu/aarch64/cortex-a53/cache.S deleted file mode 100644 index 7f295a2b02..0000000000 --- a/libcpu/aarch64/cortex-a53/cache.S +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-03-17 bigmagic first version - */ - -/* - * void __asm_dcache_level(level) - * - * flush or invalidate one level cache. - * - * x0: cache level - * x1: 0 clean & invalidate, 1 invalidate only - * x2~x9: clobbered - */ -.globl __asm_dcache_level -__asm_dcache_level: - lsl x12, x0, #1 - msr csselr_el1, x12 /* select cache level */ - isb /* sync change of cssidr_el1 */ - mrs x6, ccsidr_el1 /* read the new cssidr_el1 */ - and x2, x6, #7 /* x2 <- log2(cache line size)-4 */ - add x2, x2, #4 /* x2 <- log2(cache line size) */ - mov x3, #0x3ff - and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */ - clz w5, w3 /* bit position of #ways */ - mov x4, #0x7fff - and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */ - /* x12 <- cache level << 1 */ - /* x2 <- line length offset */ - /* x3 <- number of cache ways - 1 */ - /* x4 <- number of cache sets - 1 */ - /* x5 <- bit position of #ways */ - -loop_set: - mov x6, x3 /* x6 <- working copy of #ways */ -loop_way: - lsl x7, x6, x5 - orr x9, x12, x7 /* map way and level to cisw value */ - lsl x7, x4, x2 - orr x9, x9, x7 /* map set number to cisw value */ - tbz w1, #0, 1f - dc isw, x9 - b 2f -1: dc cisw, x9 /* clean & invalidate by set/way */ -2: subs x6, x6, #1 /* decrement the way */ - b.ge loop_way - subs x4, x4, #1 /* decrement the set */ - b.ge loop_set - - ret - -/* - * void __asm_flush_dcache_all(int invalidate_only) - * - * x0: 0 clean & invalidate, 1 invalidate only - * - * flush or invalidate all data cache by SET/WAY. - */ -.globl __asm_dcache_all -__asm_dcache_all: - mov x1, x0 - dsb sy - mrs x10, clidr_el1 /* read clidr_el1 */ - lsr x11, x10, #24 - and x11, x11, #0x7 /* x11 <- loc */ - cbz x11, finished /* if loc is 0, exit */ - mov x15, lr - mov x0, #0 /* start flush at cache level 0 */ - /* x0 <- cache level */ - /* x10 <- clidr_el1 */ - /* x11 <- loc */ - /* x15 <- return address */ - -loop_level: - lsl x12, x0, #1 - add x12, x12, x0 /* x0 <- tripled cache level */ - lsr x12, x10, x12 - and x12, x12, #7 /* x12 <- cache type */ - cmp x12, #2 - b.lt skip /* skip if no cache or icache */ - bl __asm_dcache_level /* x1 = 0 flush, 1 invalidate */ -skip: - add x0, x0, #1 /* increment cache level */ - cmp x11, x0 - b.gt loop_level - - mov x0, #0 - msr csselr_el1, x0 /* restore csselr_el1 */ - dsb sy - isb - mov lr, x15 - -finished: - ret - -.globl __asm_flush_dcache_all -__asm_flush_dcache_all: - mov x0, #0 - b __asm_dcache_all - -.globl __asm_invalidate_dcache_all -__asm_invalidate_dcache_all: - mov x0, #0x1 - b __asm_dcache_all - -/* - * void __asm_flush_dcache_range(start, end) - * - * clean & invalidate data cache in the range - * - * x0: start address - * x1: end address - */ -.globl __asm_flush_dcache_range -__asm_flush_dcache_range: - mrs x3, ctr_el0 - lsr x3, x3, #16 - and x3, x3, #0xf - mov x2, #4 - lsl x2, x2, x3 /* cache line size */ - - /* x2 <- minimal cache line size in cache system */ - sub x3, x2, #1 - bic x0, x0, x3 -1: dc civac, x0 /* clean & invalidate data or unified cache */ - add x0, x0, x2 - cmp x0, x1 - b.lo 1b - dsb sy - ret - -/* - * void __asm_invalidate_icache_all(void) - * - * invalidate all tlb entries. - */ -.globl __asm_invalidate_icache_all -__asm_invalidate_icache_all: - ic ialluis - isb sy - ret - -.globl __asm_flush_l3_cache -__asm_flush_l3_cache: - mov x0, #0 /* return status as success */ - ret \ No newline at end of file diff --git a/libcpu/aarch64/cortex-a53/context_gcc.S b/libcpu/aarch64/cortex-a53/context_gcc.S deleted file mode 100644 index 934db7ed84..0000000000 --- a/libcpu/aarch64/cortex-a53/context_gcc.S +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-06 ZhaoXiaowei the first version - */ - - /* - *enable gtimer - */ -.globl rt_hw_gtimer_enable -rt_hw_gtimer_enable: - MOV X0,#1 - MSR CNTP_CTL_EL0,X0 - RET - -/* - *set gtimer CNTP_TVAL_EL0 value - */ -.globl rt_hw_set_gtimer_val -rt_hw_set_gtimer_val: - MSR CNTP_TVAL_EL0,X0 - RET - -/* - *get gtimer CNTP_TVAL_EL0 value - */ -.globl rt_hw_get_gtimer_val -rt_hw_get_gtimer_val: - MRS X0,CNTP_TVAL_EL0 - RET - - -.globl rt_hw_get_cntpct_val -rt_hw_get_cntpct_val: - MRS X0, CNTPCT_EL0 - RET - -/* - *get gtimer frq value - */ -.globl rt_hw_get_gtimer_frq -rt_hw_get_gtimer_frq: - MRS X0,CNTFRQ_EL0 - RET - -.macro SAVE_CONTEXT - - /* Switch to use the EL0 stack pointer. */ - MSR SPSEL, #0 - - /* Save the entire context. */ - STP X0, X1, [SP, #-0x10]! - STP X2, X3, [SP, #-0x10]! - STP X4, X5, [SP, #-0x10]! - STP X6, X7, [SP, #-0x10]! - STP X8, X9, [SP, #-0x10]! - STP X10, X11, [SP, #-0x10]! - STP X12, X13, [SP, #-0x10]! - STP X14, X15, [SP, #-0x10]! - STP X16, X17, [SP, #-0x10]! - STP X18, X19, [SP, #-0x10]! - STP X20, X21, [SP, #-0x10]! - STP X22, X23, [SP, #-0x10]! - STP X24, X25, [SP, #-0x10]! - STP X26, X27, [SP, #-0x10]! - STP X28, X29, [SP, #-0x10]! - STP X30, XZR, [SP, #-0x10]! - - MRS X0, CurrentEL - CMP X0, 0xc - B.EQ 3f - CMP X0, 0x8 - B.EQ 2f - CMP X0, 0x4 - B.EQ 1f - B . -3: - MRS X3, SPSR_EL3 - /* Save the ELR. */ - MRS X2, ELR_EL3 - B 0f -2: - MRS X3, SPSR_EL2 - /* Save the ELR. */ - MRS X2, ELR_EL2 - B 0f -1: - MRS X3, SPSR_EL1 - MRS X2, ELR_EL1 - B 0f -0: - - STP X2, X3, [SP, #-0x10]! - - MOV X0, SP /* Move SP into X0 for saving. */ - - /* Switch to use the ELx stack pointer. */ - MSR SPSEL, #1 - - .endm - -.macro SAVE_CONTEXT_T - - /* Switch to use the EL0 stack pointer. */ - MSR SPSEL, #0 - - /* Save the entire context. */ - STP X0, X1, [SP, #-0x10]! - STP X2, X3, [SP, #-0x10]! - STP X4, X5, [SP, #-0x10]! - STP X6, X7, [SP, #-0x10]! - STP X8, X9, [SP, #-0x10]! - STP X10, X11, [SP, #-0x10]! - STP X12, X13, [SP, #-0x10]! - STP X14, X15, [SP, #-0x10]! - STP X16, X17, [SP, #-0x10]! - STP X18, X19, [SP, #-0x10]! - STP X20, X21, [SP, #-0x10]! - STP X22, X23, [SP, #-0x10]! - STP X24, X25, [SP, #-0x10]! - STP X26, X27, [SP, #-0x10]! - STP X28, X29, [SP, #-0x10]! - STP X30, XZR, [SP, #-0x10]! - - MRS X0, CurrentEL - CMP X0, 0xc - B.EQ 3f - CMP X0, 0x8 - B.EQ 2f - CMP X0, 0x4 - B.EQ 1f - B . -3: - MRS X3, SPSR_EL3 - MOV X2, X30 - B 0f -2: - MRS X3, SPSR_EL2 - MOV X2, X30 - B 0f -1: - MRS X3, SPSR_EL1 - MOV X2, X30 - B 0f -0: - - STP X2, X3, [SP, #-0x10]! - - MOV X0, SP /* Move SP into X0 for saving. */ - - /* Switch to use the ELx stack pointer. */ - MSR SPSEL, #1 - - .endm - -.macro RESTORE_CONTEXT - - /* Switch to use the EL0 stack pointer. */ - MSR SPSEL, #0 - - /* Set the SP to point to the stack of the task being restored. */ - MOV SP, X0 - - LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */ - - MRS X0, CurrentEL - CMP X0, 0xc - B.EQ 3f - CMP X0, 0x8 - B.EQ 2f - CMP X0, 0x4 - B.EQ 1f - B . -3: - MSR SPSR_EL3, X3 - MSR ELR_EL3, X2 - B 0f -2: - MSR SPSR_EL2, X3 - MSR ELR_EL2, X2 - B 0f -1: - MSR SPSR_EL1, X3 - MSR ELR_EL1, X2 - B 0f -0: - - LDP X30, XZR, [SP], #0x10 - LDP X28, X29, [SP], #0x10 - LDP X26, X27, [SP], #0x10 - LDP X24, X25, [SP], #0x10 - LDP X22, X23, [SP], #0x10 - LDP X20, X21, [SP], #0x10 - LDP X18, X19, [SP], #0x10 - LDP X16, X17, [SP], #0x10 - LDP X14, X15, [SP], #0x10 - LDP X12, X13, [SP], #0x10 - LDP X10, X11, [SP], #0x10 - LDP X8, X9, [SP], #0x10 - LDP X6, X7, [SP], #0x10 - LDP X4, X5, [SP], #0x10 - LDP X2, X3, [SP], #0x10 - LDP X0, X1, [SP], #0x10 - - /* Switch to use the ELx stack pointer. _RB_ Might not be required. */ - MSR SPSEL, #1 - - ERET - - .endm - -.text -/* - * rt_base_t rt_hw_interrupt_disable(); - */ -.globl rt_hw_interrupt_disable -rt_hw_interrupt_disable: - MRS X0, DAIF - MSR DAIFSet, #3 - DSB SY - RET - -/* - * void rt_hw_interrupt_enable(rt_base_t level); - */ -.globl rt_hw_interrupt_enable -rt_hw_interrupt_enable: - DSB SY - MOV X1, #0xC0 - ANDS X0, X0, X1 - B.NE rt_hw_interrupt_enable_exit - MSR DAIFClr, #3 -rt_hw_interrupt_enable_exit: - RET - -/* - * void rt_hw_context_switch_to(rt_ubase_t to); - * r0 --> to - */ -.globl rt_hw_context_switch_to -rt_hw_context_switch_to: - LDR X0, [X0] - RESTORE_CONTEXT - -.text -/* - * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); - * r0 --> from - * r1 --> to - */ -.globl rt_hw_context_switch -rt_hw_context_switch: - - MOV X8,X0 - MOV X9,X1 - - SAVE_CONTEXT_T - - STR X0, [X8] // store sp in preempted tasks TCB - LDR X0, [X9] // get new task stack pointer - - RESTORE_CONTEXT - -/* - * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to); - */ -.globl rt_thread_switch_interrupt_flag -.globl rt_interrupt_from_thread -.globl rt_interrupt_to_thread -.globl rt_hw_context_switch_interrupt -rt_hw_context_switch_interrupt: - ADR X2, rt_thread_switch_interrupt_flag - LDR X3, [X2] - CMP X3, #1 - B.EQ _reswitch - ADR X4, rt_interrupt_from_thread // set rt_interrupt_from_thread - MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1 - STR X0, [X4] - STR X3, [X2] -_reswitch: - ADR X2, rt_interrupt_to_thread // set rt_interrupt_to_thread - STR X1, [X2] - RET - -.text - -// -- Exception handlers ---------------------------------- - - .align 8 -.globl vector_fiq -vector_fiq: - SAVE_CONTEXT - STP X0, X1, [SP, #-0x10]! - BL rt_hw_trap_fiq - LDP X0, X1, [SP], #0x10 - RESTORE_CONTEXT - -.globl rt_interrupt_enter -.globl rt_interrupt_leave -.globl rt_thread_switch_interrupt_flag -.globl rt_interrupt_from_thread -.globl rt_interrupt_to_thread - - -// ------------------------------------------------------------------- - - .align 8 -.globl vector_irq -vector_irq: - SAVE_CONTEXT - STP X0, X1, [SP, #-0x10]! - - BL rt_interrupt_enter - BL rt_hw_trap_irq - BL rt_interrupt_leave - - LDP X0, X1, [SP], #0x10 - - // if rt_thread_switch_interrupt_flag set, jump to - // rt_hw_context_switch_interrupt_do and don't return - ADR X1, rt_thread_switch_interrupt_flag - LDR X2, [X1] - CMP X2, #1 - B.NE vector_irq_exit - - MOV X2, #0 // clear flag - STR X2, [X1] - - ADR X3, rt_interrupt_from_thread - LDR X4, [X3] - STR x0, [X4] // store sp in preempted tasks's TCB - - ADR x3, rt_interrupt_to_thread - LDR X4, [X3] - LDR x0, [X4] // get new task's stack pointer - -vector_irq_exit: - RESTORE_CONTEXT - -// ------------------------------------------------- - - .align 8 - .globl vector_error -vector_error: - SAVE_CONTEXT - BL rt_hw_trap_error - B . diff --git a/libcpu/aarch64/cortex-a53/cp15.h b/libcpu/aarch64/cortex-a53/cp15.h deleted file mode 100644 index f3ffd6f857..0000000000 --- a/libcpu/aarch64/cortex-a53/cp15.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-09-15 Bernard first version - */ - -#ifndef __CP15_H__ -#define __CP15_H__ - -#ifndef __STATIC_FORCEINLINE -#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline -#endif - -#define __WFI() __asm__ volatile ("wfi":::"memory") - -#define __WFE() __asm__ volatile ("wfe":::"memory") - -#define __SEV() __asm__ volatile ("sev") - -__STATIC_FORCEINLINE void __ISB(void) -{ - __asm__ volatile ("isb 0xF":::"memory"); -} - -/** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -__STATIC_FORCEINLINE void __DSB(void) -{ - __asm__ volatile ("dsb 0xF":::"memory"); -} - -/** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ - -__STATIC_FORCEINLINE void __DMB(void) -{ - __asm__ volatile ("dmb 0xF":::"memory"); -} - -#ifdef RT_USING_SMP -static inline void send_ipi_msg(int cpu, int ipi_vector) -{ - IPI_MAILBOX_SET(cpu) = 1 << ipi_vector; -} - -static inline void setup_bootstrap_addr(int cpu, int addr) -{ - CORE_MAILBOX3_SET(cpu) = addr; -} - -static inline void enable_cpu_ipi_intr(int cpu) -{ - COREMB_INTCTL(cpu) = IPI_MAILBOX_INT_MASK; -} - -static inline void enable_cpu_timer_intr(int cpu) -{ - CORETIMER_INTCTL(cpu) = 0x8; -} - -static inline void enable_cntv(void) -{ - rt_uint32_t cntv_ctl; - cntv_ctl = 1; - asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL -} - -static inline void disable_cntv(void) -{ - rt_uint32_t cntv_ctl; - cntv_ctl = 0; - asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL -} - -static inline void mask_cntv(void) -{ - rt_uint32_t cntv_ctl; - cntv_ctl = 2; - asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL -} - -static inline void unmask_cntv(void) -{ - rt_uint32_t cntv_ctl; - cntv_ctl = 1; - asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL -} - -static inline rt_uint64_t read_cntvct(void) -{ - rt_uint32_t val,val1; - asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (val),"=r" (val1)); - return (val); -} - -static inline rt_uint64_t read_cntvoff(void) -{ - - rt_uint64_t val; - asm volatile("mrrc p15, 4, %Q0, %R0, c14" : "=r" (val)); - return (val); -} - -static inline rt_uint32_t read_cntv_tval(void) -{ - rt_uint32_t val; - asm volatile ("mrc p15, 0, %0, c14, c3, 0" : "=r"(val) ); - return val; -} - - -static inline void write_cntv_tval(rt_uint32_t val) -{ - asm volatile ("mcr p15, 0, %0, c14, c3, 0" :: "r"(val) ); - return; -} - -static inline rt_uint32_t read_cntfrq(void) -{ - rt_uint32_t val; - asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val) ); - return val; -} - - -static inline rt_uint32_t read_cntctrl(void) -{ - rt_uint32_t val; - asm volatile ("mrc p15, 0, %0, c14, c1, 0" : "=r"(val) ); - return val; -} - -static inline uint32_t write_cntctrl(uint32_t val) -{ - - asm volatile ("mcr p15, 0, %0, c14, c1, 0" : :"r"(val) ); - return val; -} -#endif - -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(rt_ubase_t addr); -void rt_hw_mmu_init(void); -void rt_hw_vector_init(void); - -void set_timer_counter(unsigned int counter); -void set_timer_control(unsigned int control); -#endif diff --git a/libcpu/aarch64/cortex-a53/cpu.c b/libcpu/aarch64/cortex-a53/cpu.c deleted file mode 100644 index 962a53a071..0000000000 --- a/libcpu/aarch64/cortex-a53/cpu.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2006-2019, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-09-15 Bernard first version - * 2019-07-28 zdzn add smp support - */ - -#include -#include -#include -#include "cp15.h" - -int rt_hw_cpu_id(void) -{ - int cpu_id; - rt_base_t value; - - __asm__ volatile ( - "mrs %0, mpidr_el1" - :"=r"(value) - ); - cpu_id = value & 0xf; - return cpu_id; -}; - -#ifdef RT_USING_SMP -void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock) -{ - lock->slock = 0; -} - -void rt_hw_spin_lock(rt_hw_spinlock_t *lock) -{ - unsigned long tmp; - unsigned long newval; - rt_hw_spinlock_t lockval; - __asm__ __volatile__( - "pld [%0]" - ::"r"(&lock->slock) - ); - - __asm__ __volatile__( - "1: ldrex %0, [%3]\n" - " add %1, %0, %4\n" - " strex %2, %1, [%3]\n" - " teq %2, #0\n" - " bne 1b" - : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) - : "r" (&lock->slock), "I" (1 << 16) - : "cc"); - - while (lockval.tickets.next != lockval.tickets.owner) { - __WFE(); - lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner); - } - - __DMB(); -} - -void rt_hw_spin_unlock(rt_hw_spinlock_t *lock) -{ - __DMB(); - lock->tickets.owner++; - __DSB(); - __SEV(); -} -#endif /*RT_USING_SMP*/ - -/** - * @addtogroup ARM CPU - */ -/*@{*/ - -/** 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/aarch64/cortex-a53/cpu_gcc.S b/libcpu/aarch64/cortex-a53/cpu_gcc.S deleted file mode 100644 index b8c8b8768c..0000000000 --- a/libcpu/aarch64/cortex-a53/cpu_gcc.S +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Date Author Notes - * 2018-10-06 ZhaoXiaowei the first version - */ - -.text -.globl rt_hw_get_current_el -rt_hw_get_current_el: - MRS X0, CurrentEL - CMP X0, 0xc - B.EQ 3f - CMP X0, 0x8 - B.EQ 2f - CMP X0, 0x4 - B.EQ 1f - - LDR X0, =0 - B 0f -3: - LDR X0, =3 - B 0f -2: - LDR X0, =2 - B 0f -1: - LDR X0, =1 - B 0f -0: - RET - - -.globl rt_hw_set_current_vbar -rt_hw_set_current_vbar: - MRS X1, CurrentEL - CMP X1, 0xc - B.EQ 3f - CMP X1, 0x8 - B.EQ 2f - CMP X1, 0x4 - B.EQ 1f - B 0f -3: - MSR VBAR_EL3,X0 - B 0f -2: - MSR VBAR_EL2,X0 - B 0f -1: - MSR VBAR_EL1,X0 - B 0f -0: - RET - - -.globl rt_hw_set_elx_env -rt_hw_set_elx_env: - MRS X1, CurrentEL - CMP X1, 0xc - B.EQ 3f - CMP X1, 0x8 - B.EQ 2f - CMP X1, 0x4 - B.EQ 1f - B 0f -3: - MRS X0, SCR_EL3 - ORR X0, X0, #0xF /* SCR_EL3.NS|IRQ|FIQ|EA */ - MSR SCR_EL3, X0 - B 0f -2: - MRS X0, HCR_EL2 - ORR X0, X0, #0x38 - MSR HCR_EL2, X0 - B 0f -1: - B 0f -0: - RET diff --git a/libcpu/aarch64/cortex-a53/interrupt.h b/libcpu/aarch64/cortex-a53/interrupt.h index 3533d3818c..8e741ed4e6 100644 --- a/libcpu/aarch64/cortex-a53/interrupt.h +++ b/libcpu/aarch64/cortex-a53/interrupt.h @@ -1,11 +1,11 @@ - /* * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes + * Date Author Notes + * 2020-04-16 bigmagic first version */ #ifndef __INTERRUPT_H__ @@ -19,8 +19,6 @@ #define INT_IRQ 0x00 #define INT_FIQ 0x01 -//void rt_hw_vector_init(void); - void rt_hw_interrupt_init(void); void rt_hw_interrupt_mask(int vector); void rt_hw_interrupt_umask(int vector); diff --git a/libcpu/aarch64/cortex-a53/mmu.c b/libcpu/aarch64/cortex-a53/mmu.c deleted file mode 100644 index b799143084..0000000000 --- a/libcpu/aarch64/cortex-a53/mmu.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-02-20 bigmagic first version - */ -#include -#include -#include - -#define TTBR_CNP 1 - -typedef unsigned long int uint64_t; - -static unsigned long main_tbl[512 * 20] __attribute__((aligned (4096))); - -#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) - -#define PMD_TYPE_SECT (1 << 0) - -#define PMD_TYPE_TABLE (3 << 0) - -#define PTE_TYPE_PAGE (3 << 0) - -#define BITS_PER_VA 39 - -/* Granule size of 4KB is being used */ -#define GRANULE_SIZE_SHIFT 12 -#define GRANULE_SIZE (1 << GRANULE_SIZE_SHIFT) -#define XLAT_ADDR_MASK ((1UL << BITS_PER_VA) - GRANULE_SIZE) - -#define PMD_TYPE_MASK (3 << 0) - -int free_idx = 1; - -void __asm_invalidate_icache_all(void); -void __asm_flush_dcache_all(void); -int __asm_flush_l3_cache(void); -void __asm_flush_dcache_range(unsigned long long start, unsigned long long end); -void __asm_invalidate_dcache_all(void); -void __asm_invalidate_icache_all(void); - -void mmu_memset(char *dst, char v, size_t len) -{ - while (len--) - { - *dst++ = v; - } -} - -static unsigned long __page_off = 0; -static unsigned long get_free_page(void) -{ - __page_off += 512; - return (unsigned long)(main_tbl + __page_off); -} - - -static inline unsigned int get_sctlr(void) -{ - unsigned int val; - asm volatile("mrs %0, sctlr_el1" : "=r" (val) : : "cc"); - return val; -} - -static inline void set_sctlr(unsigned int val) -{ - asm volatile("msr sctlr_el1, %0" : : "r" (val) : "cc"); - asm volatile("isb"); -} - -void mmu_init(void) -{ - unsigned long val64; - unsigned long val32; - - val64 = 0x007f6eUL; - __asm__ volatile("msr MAIR_EL1, %0\n dsb sy\n"::"r"(val64)); - __asm__ volatile("mrs %0, MAIR_EL1\n dsb sy\n":"=r"(val64)); - - //TCR_EL1 - val32 = (16UL << 0)//48bit - | (0x0UL << 6) - | (0x0UL << 7) - | (0x3UL << 8) - | (0x3UL << 10)//Inner Shareable - | (0x2UL << 12) - | (0x0UL << 14)//4K - | (0x0UL << 16) - | (0x0UL << 22) - | (0x1UL << 23) - | (0x2UL << 30) - | (0x1UL << 32) - | (0x0UL << 35) - | (0x0UL << 36) - | (0x0UL << 37) - | (0x0UL << 38); - __asm__ volatile("msr TCR_EL1, %0\n"::"r"(val32)); - __asm__ volatile("mrs %0, TCR_EL1\n":"=r"(val32)); - - __asm__ volatile("msr TTBR0_EL1, %0\n dsb sy\n"::"r"(main_tbl)); - __asm__ volatile("mrs %0, TTBR0_EL1\n dsb sy\n":"=r"(val64)); - - mmu_memset((char *)main_tbl, 0, 4096); -} - -void mmu_enable(void) -{ - unsigned long val64; - unsigned long val32; - - __asm__ volatile("mrs %0, SCTLR_EL1\n":"=r"(val64)); - val64 &= ~0x1000; //disable I - __asm__ volatile("dmb sy\n msr SCTLR_EL1, %0\n isb sy\n"::"r"(val64)); - - __asm__ volatile("IC IALLUIS\n dsb sy\n isb sy\n"); - __asm__ volatile("tlbi vmalle1\n dsb sy\n isb sy\n"); - - //SCTLR_EL1, turn on mmu - __asm__ volatile("mrs %0, SCTLR_EL1\n":"=r"(val32)); - val32 |= 0x1005; //enable mmu, I C M - __asm__ volatile("dmb sy\n msr SCTLR_EL1, %0\nisb sy\n"::"r"(val32)); - rt_hw_icache_enable(); - rt_hw_dcache_enable(); - -} - -static int map_single_page_2M(unsigned long* lv0_tbl, unsigned long va, unsigned long pa, unsigned long attr) -{ - int level; - unsigned long* cur_lv_tbl = lv0_tbl; - unsigned long page; - unsigned long off; - int level_shift = 39; - - if (va & (0x200000UL - 1)) - { - return MMU_MAP_ERROR_VANOTALIGN; - } - if (pa & (0x200000UL - 1)) - { - return MMU_MAP_ERROR_PANOTALIGN; - } - for (level = 0; level < 2; level++) - { - off = (va >> level_shift); - off &= MMU_LEVEL_MASK; - if ((cur_lv_tbl[off] & 1) == 0) - { - page = get_free_page(); - if (!page) - { - return MMU_MAP_ERROR_NOPAGE; - } - mmu_memset((char *)page, 0, 4096); - cur_lv_tbl[off] = page | 0x3UL; - } - page = cur_lv_tbl[off]; - if (!(page & 0x2)) - { - //is block! error! - return MMU_MAP_ERROR_CONFLICT; - } - cur_lv_tbl = (unsigned long*)(page & 0x0000fffffffff000UL); - level_shift -= 9; - } - attr &= 0xfff0000000000ffcUL; - pa |= (attr | 0x1UL); //block - off = (va >> 21); - off &= MMU_LEVEL_MASK; - cur_lv_tbl[off] = pa; - return 0; -} - -int armv8_map_2M(unsigned long va, unsigned long pa, int count, unsigned long attr) -{ - int i; - int ret; - - if (va & (0x200000 - 1)) - { - return -1; - } - if (pa & (0x200000 - 1)) - { - return -1; - } - for (i = 0; i < count; i++) - { - ret = map_single_page_2M((unsigned long *)main_tbl, va, pa, attr); - va += 0x200000; - pa += 0x200000; - if (ret != 0) - { - return ret; - } - } - return 0; -} - -static void set_table(uint64_t *pt, uint64_t *table_addr) -{ - uint64_t val; - val = (0x3UL | (uint64_t)table_addr); - *pt = val; -} - -void mmu_memset2(unsigned char *dst, char v, int len) -{ - while (len--) - { - *dst++ = v; - } -} - -static uint64_t *create_table(void) -{ - uint64_t *new_table = (uint64_t *)((unsigned char *)&main_tbl[0] + free_idx * 4096); //+ free_idx * GRANULE_SIZE; - /* Mark all entries as invalid */ - mmu_memset2((unsigned char *)new_table, 0, 4096); - free_idx++; - return new_table; -} - -static int pte_type(uint64_t *pte) -{ - return *pte & PMD_TYPE_MASK; -} - -static int level2shift(int level) -{ - /* Page is 12 bits wide, every level translates 9 bits */ - return (12 + 9 * (3 - level)); -} - -static uint64_t *get_level_table(uint64_t *pte) -{ - uint64_t *table = (uint64_t *)(*pte & XLAT_ADDR_MASK); - - if (pte_type(pte) != PMD_TYPE_TABLE) - { - table = create_table(); - set_table(pte, table); - } - return table; -} - -static void map_region(uint64_t virt, uint64_t phys, uint64_t size, uint64_t attr) -{ - uint64_t block_size = 0; - uint64_t block_shift = 0; - uint64_t *pte; - uint64_t idx = 0; - uint64_t addr = 0; - uint64_t *table = 0; - int level = 0; - - addr = virt; - while (size) - { - table = &main_tbl[0]; - for (level = 0; level < 4; level++) - { - block_shift = level2shift(level); - idx = addr >> block_shift; - idx = idx%512; - block_size = (uint64_t)(1L << block_shift); - pte = table + idx; - - if (size >= block_size && IS_ALIGNED(addr, block_size)) - { - attr &= 0xfff0000000000ffcUL; - if(level != 3) - { - *pte = phys | (attr | 0x1UL); - } - else - { - *pte = phys | (attr | 0x3UL); - } - addr += block_size; - phys += block_size; - size -= block_size; - break; - } - table = get_level_table(pte); - } - } -} - -void armv8_map(unsigned long va, unsigned long pa, unsigned long size, unsigned long attr) -{ - map_region(va, pa, size, attr); -} - -void rt_hw_dcache_enable(void) -{ - if (!(get_sctlr() & CR_M)) - { - rt_kprintf("please init mmu!\n"); - } - else - { - set_sctlr(get_sctlr() | CR_C); - } -} - -void rt_hw_dcache_flush_all(void) -{ - int ret; - - __asm_flush_dcache_all(); - ret = __asm_flush_l3_cache(); - if (ret) - { - rt_kprintf("flushing dcache returns 0x%x\n", ret); - } - else - { - rt_kprintf("flushing dcache successfully.\n"); - } -} - -void rt_hw_dcache_flush_range(unsigned long start_addr, unsigned long size) -{ - __asm_flush_dcache_range(start_addr, start_addr + size); -} -void rt_hw_dcache_invalidate_range(unsigned long start_addr,unsigned long size) -{ - __asm_flush_dcache_range(start_addr, start_addr + size); -} - -void rt_hw_dcache_invalidate_all(void) -{ - __asm_invalidate_dcache_all(); -} - -void rt_hw_dcache_disable(void) -{ - /* if cache isn't enabled no need to disable */ - if(!(get_sctlr() & CR_C)) - { - rt_kprintf("need enable cache!\n"); - return; - } - set_sctlr(get_sctlr() & ~CR_C); -} - -//icache -void rt_hw_icache_enable(void) -{ - __asm_invalidate_icache_all(); - set_sctlr(get_sctlr() | CR_I); -} - -void rt_hw_icache_invalidate_all(void) -{ - __asm_invalidate_icache_all(); -} - -void rt_hw_icache_disable(void) -{ - set_sctlr(get_sctlr() & ~CR_I); -} \ No newline at end of file diff --git a/libcpu/aarch64/cortex-a53/mmu.h b/libcpu/aarch64/cortex-a53/mmu.h deleted file mode 100644 index 6a66472c79..0000000000 --- a/libcpu/aarch64/cortex-a53/mmu.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-02-20 bigmagic first version - */ - -#ifndef __MMU_H__ -#define __MMU_H__ - -/* - * CR1 bits (CP#15 CR1) - */ -#define CR_M (1 << 0) /* MMU enable */ -#define CR_A (1 << 1) /* Alignment abort enable */ -#define CR_C (1 << 2) /* Dcache enable */ -#define CR_W (1 << 3) /* Write buffer enable */ -#define CR_P (1 << 4) /* 32-bit exception handler */ -#define CR_D (1 << 5) /* 32-bit data address range */ -#define CR_L (1 << 6) /* Implementation defined */ -#define CR_B (1 << 7) /* Big endian */ -#define CR_S (1 << 8) /* System MMU protection */ -#define CR_R (1 << 9) /* ROM MMU protection */ -#define CR_F (1 << 10) /* Implementation defined */ -#define CR_Z (1 << 11) /* Implementation defined */ -#define CR_I (1 << 12) /* Icache enable */ -#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */ -#define CR_RR (1 << 14) /* Round Robin cache replacement */ -#define CR_L4 (1 << 15) /* LDR pc can set T bit */ -#define CR_DT (1 << 16) -#define CR_IT (1 << 18) -#define CR_ST (1 << 19) -#define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */ -#define CR_U (1 << 22) /* Unaligned access operation */ -#define CR_XP (1 << 23) /* Extended page tables */ -#define CR_VE (1 << 24) /* Vectored interrupts */ -#define CR_EE (1 << 25) /* Exception (Big) Endian */ -#define CR_TRE (1 << 28) /* TEX remap enable */ -#define CR_AFE (1 << 29) /* Access flag enable */ -#define CR_TE (1 << 30) /* Thumb exception enable */ - -#define MMU_LEVEL_MASK 0x1ffUL -#define MMU_MAP_ERROR_VANOTALIGN -1 -#define MMU_MAP_ERROR_PANOTALIGN -2 -#define MMU_MAP_ERROR_NOPAGE -3 -#define MMU_MAP_ERROR_CONFLICT -4 - -#define MEM_ATTR_MEMORY ((0x1UL << 10) | (0x2UL << 8) | (0x0UL << 6) | (0x1UL << 2)) -#define MEM_ATTR_IO ((0x1UL << 10) | (0x2UL << 8) | (0x0UL << 6) | (0x2UL << 2)) - -#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000) - -void mmu_init(void); - -void mmu_enable(void); - -int armv8_map_2M(unsigned long va, unsigned long pa, int count, unsigned long attr); - -void armv8_map(unsigned long va, unsigned long pa, unsigned long size, unsigned long attr); - -//dcache -void rt_hw_dcache_enable(void); -void rt_hw_dcache_flush_all(void); -void rt_hw_dcache_flush_range(unsigned long start_addr, unsigned long size); -void rt_hw_dcache_invalidate_range(unsigned long start_addr,unsigned long size); -void rt_hw_dcache_invalidate_all(void); -void rt_hw_dcache_disable(void); - -//icache -void rt_hw_icache_enable(void); -void rt_hw_icache_invalidate_all(void); -void rt_hw_icache_disable(void); - - -#endif /*__MMU_H__*/ diff --git a/libcpu/aarch64/cortex-a53/startup_gcc.S b/libcpu/aarch64/cortex-a53/startup_gcc.S deleted file mode 100644 index ea4268148c..0000000000 --- a/libcpu/aarch64/cortex-a53/startup_gcc.S +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ - - .global Reset_Handler - .section ".start", "ax" -Reset_Handler: - nop diff --git a/libcpu/aarch64/cortex-a53/vector_gcc.S b/libcpu/aarch64/cortex-a53/vector_gcc.S deleted file mode 100644 index fc88cce7f8..0000000000 --- a/libcpu/aarch64/cortex-a53/vector_gcc.S +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Date Author Notes - * 2018-10-06 ZhaoXiaowei the first version - */ - -.text - -.globl system_vectors -.globl vector_error -.globl vector_irq -.globl vector_fiq - -system_vectors: -.align 11 - .set VBAR, system_vectors - .org VBAR - // Exception from CurrentEL (EL1) with SP_EL0 (SPSEL=1) - .org (VBAR + 0x00 + 0) - B vector_error // Synchronous - .org (VBAR + 0x80 + 0) - B vector_irq // IRQ/vIRQ - .org (VBAR + 0x100 + 0) - B vector_fiq // FIQ/vFIQ - .org (VBAR + 0x180 + 0) - B vector_error // Error/vError - - // Exception from CurrentEL (EL1) with SP_ELn - .org (VBAR + 0x200 + 0) - B vector_error // Synchronous - .org (VBAR + 0x280 + 0) - B vector_irq // IRQ/vIRQ - .org (VBAR + 0x300 + 0) - B vector_fiq // FIQ/vFIQ - .org (VBAR + 0x380 + 0) - B vector_error - - // Exception from lower EL, aarch64 - .org (VBAR + 0x400 + 0) - B vector_error - .org (VBAR + 0x480 + 0) - B vector_error - .org (VBAR + 0x500 + 0) - B vector_error - .org (VBAR + 0x580 + 0) - B vector_error - - // Exception from lower EL, aarch32 - .org (VBAR + 0x600 + 0) - B vector_error - .org (VBAR + 0x680 + 0) - B vector_error - .org (VBAR + 0x700 + 0) - B vector_error - .org (VBAR + 0x780 + 0) - B vector_error - .org (VBAR + 0x800 + 0) - B vector_error diff --git a/libcpu/aarch64/cortex-a57/SConscript b/libcpu/aarch64/cortex-a57/SConscript new file mode 100644 index 0000000000..c6a4817802 --- /dev/null +++ b/libcpu/aarch64/cortex-a57/SConscript @@ -0,0 +1,13 @@ +# RT-Thread building script for component + +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') + Glob('*.S') +CPPPATH = [cwd] + +group = DefineGroup('common', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/aarch64/cortex-a57/entry_point.S b/libcpu/aarch64/cortex-a57/entry_point.S new file mode 100644 index 0000000000..6d2c69226b --- /dev/null +++ b/libcpu/aarch64/cortex-a57/entry_point.S @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Date Author Notes + * 2020-01-15 bigmagic the first version + */ + +.section ".text.entrypoint" + +.set EL1_stack, __el1_stack + +.global _start + +// This symbol is set to 0x80000 in ld script. That is the address that raspi3's firmware +// loads 'kernel8.img' file in. +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 // MPIDR_EL1: Multi-Processor Affinity Register + and x1, x1, #3 + cbz x1, .L__cpu_0 // .L prefix is the local label in ELF + + // cpu id > 0, stop + // cpu id == 0 will also goto here after returned from entry() if possible +.L__current_cpu_idle: + wfe + b .L__current_cpu_idle + +.L__cpu_0: // cpu id == 0 + + // set stack before our code + + /* Define stack pointer for current exception level */ + // ldr x2, =EL1_stack + // mov sp, x2 + + ldr x1, =_start + + // set up EL1 + mrs x0, CurrentEL // CurrentEL Register. bit 2, 3. Others reserved + and x0, x0, #12 // clear reserved bits + + // running at EL3? + cmp x0, #12 // 1100b. So, EL3 + bne .L__not_in_el3 // 11? !EL3 -> 5: + + // should never be executed, just for completeness. (EL3) + mov x2, #0x5b1 + msr scr_el3, x2 // SCR_ELn Secure Configuration Register + mov x2, #0x3c9 + msr spsr_el3, x2 // SPSR_ELn. Saved Program Status Register. 1111001001 + adr x2, .L__not_in_el3 + msr elr_el3, x2 + eret // Exception Return: from EL3, continue from .L__not_in_el3 + + // running at EL2 or EL1 +.L__not_in_el3: + cmp x0, #4 // 0x04 0100 EL1 + beq .L__in_el1 // EL1 -> 5: + + // in EL2 + msr sp_el1, x1 // Set sp of EL1 to _start + + // enable CNTP for EL1 + mrs x0, cnthctl_el2 // Counter-timer Hypervisor Control register + orr x0, x0, #3 + msr cnthctl_el2, x0 + msr cntvoff_el2, xzr + + // enable AArch64 in EL1 + mov x0, #(1 << 31) // AArch64 + orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3 + msr hcr_el2, x0 + mrs x0, hcr_el2 + + // change execution level to EL1 + mov x2, #0x3c4 + msr spsr_el2, x2 // 1111000100 + adr x2, .L__in_el1 + msr elr_el2, x2 + eret // exception return. from EL2. continue from .L__in_el1 + +.L__in_el1: + mov sp, x1 // in EL1. Set sp to _start + + // Set CPACR_EL1 (Architecture Feature Access Control Register) to avoid trap from SIMD or float point instruction + mov x1, #0x00300000 // Don't trap any SIMD/FP instructions in both EL0 and EL1 + msr cpacr_el1, x1 + + mrs x1, sctlr_el1 + orr x1, x1, #(1 << 12) + bic x1, x1, #(3 << 3) + bic x1, x1, #(1 << 1) + msr sctlr_el1, x1 + + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size + +.L__clean_bss_loop: + cbz w2, .L__jump_to_entry + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, .L__clean_bss_loop + + // jump to C code, should not return +.L__jump_to_entry: + bl entry + // for failsafe, halt this core too + b .L__current_cpu_idle diff --git a/libcpu/aarch64/cortex-a57/interrupt.c b/libcpu/aarch64/cortex-a57/interrupt.c new file mode 100644 index 0000000000..d770259d61 --- /dev/null +++ b/libcpu/aarch64/cortex-a57/interrupt.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-04-16 bigmagic first version + */ + +#include +#include +#include +#include +#include + +#define MAX_HANDLERS 256 + +#ifdef RT_USING_SMP +#define rt_interrupt_nest rt_cpu_self()->irq_nest +#else +extern volatile rt_uint8_t rt_interrupt_nest; +#endif + +extern int system_vectors; + +/* exception and interrupt handler table */ +struct rt_irq_desc isr_table[MAX_HANDLERS]; + +rt_ubase_t rt_interrupt_from_thread; +rt_ubase_t rt_interrupt_to_thread; +rt_ubase_t rt_thread_switch_interrupt_flag; + +void rt_hw_vector_init(void) +{ + rt_hw_set_current_vbar((rt_ubase_t)&system_vectors); // cpu_gcc.S +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + initIRQController(); +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if (vector < MAX_HANDLERS) + { + old_handler = isr_table[vector].handler; + + if (handler != RT_NULL) + { +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); +#endif /* RT_USING_INTERRUPT_INFO */ + isr_table[vector].handler = handler; + isr_table[vector].param = param; + } + } + + return old_handler; +} \ No newline at end of file diff --git a/libcpu/aarch64/cortex-a57/interrupt.h b/libcpu/aarch64/cortex-a57/interrupt.h new file mode 100644 index 0000000000..0d2d4867c7 --- /dev/null +++ b/libcpu/aarch64/cortex-a57/interrupt.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-04-16 bigmagic first version + */ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#include +#include + +#define INT_IRQ 0x00 +#define INT_FIQ 0x01 + +void rt_hw_interrupt_init(void); +void rt_hw_interrupt_mask(int vector); +void rt_hw_interrupt_umask(int vector); + +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name); + +#endif diff --git a/libcpu/aarch64/cortex-a57/stack.c b/libcpu/aarch64/cortex-a57/stack.c new file mode 100644 index 0000000000..68222c2c67 --- /dev/null +++ b/libcpu/aarch64/cortex-a57/stack.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-23 Bernard the first version + * 2011-10-05 Bernard add thumb mode + */ +#include +#include + +#include + +#define INITIAL_SPSR_EL3 (PSTATE_EL3 | SP_EL0) +#define INITIAL_SPSR_EL2 (PSTATE_EL2 | SP_EL0) +#define INITIAL_SPSR_EL1 (PSTATE_EL1 | SP_EL0) + +/** + * 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) +{ + rt_ubase_t *stk; + rt_ubase_t current_el; + + stk = (rt_ubase_t*)stack_addr; + + *(--stk) = ( rt_ubase_t ) 11; /* X1 */ + *(--stk) = ( rt_ubase_t ) parameter; /* X0 */ + *(--stk) = ( rt_ubase_t ) 33; /* X3 */ + *(--stk) = ( rt_ubase_t ) 22; /* X2 */ + *(--stk) = ( rt_ubase_t ) 55; /* X5 */ + *(--stk) = ( rt_ubase_t ) 44; /* X4 */ + *(--stk) = ( rt_ubase_t ) 77; /* X7 */ + *(--stk) = ( rt_ubase_t ) 66; /* X6 */ + *(--stk) = ( rt_ubase_t ) 99; /* X9 */ + *(--stk) = ( rt_ubase_t ) 88; /* X8 */ + *(--stk) = ( rt_ubase_t ) 11; /* X11 */ + *(--stk) = ( rt_ubase_t ) 10; /* X10 */ + *(--stk) = ( rt_ubase_t ) 13; /* X13 */ + *(--stk) = ( rt_ubase_t ) 12; /* X12 */ + *(--stk) = ( rt_ubase_t ) 15; /* X15 */ + *(--stk) = ( rt_ubase_t ) 14; /* X14 */ + *(--stk) = ( rt_ubase_t ) 17; /* X17 */ + *(--stk) = ( rt_ubase_t ) 16; /* X16 */ + *(--stk) = ( rt_ubase_t ) 19; /* X19 */ + *(--stk) = ( rt_ubase_t ) 18; /* X18 */ + *(--stk) = ( rt_ubase_t ) 21; /* X21 */ + *(--stk) = ( rt_ubase_t ) 20; /* X20 */ + *(--stk) = ( rt_ubase_t ) 23; /* X23 */ + *(--stk) = ( rt_ubase_t ) 22; /* X22 */ + *(--stk) = ( rt_ubase_t ) 25; /* X25 */ + *(--stk) = ( rt_ubase_t ) 24; /* X24 */ + *(--stk) = ( rt_ubase_t ) 27; /* X27 */ + *(--stk) = ( rt_ubase_t ) 26; /* X26 */ + *(--stk) = ( rt_ubase_t ) 29; /* X29 */ + *(--stk) = ( rt_ubase_t ) 28; /* X28 */ + *(--stk) = ( rt_ubase_t ) 0; /* XZR - has no effect, used so there are an even number of registers. */ + *(--stk) = ( rt_ubase_t ) texit; /* X30 - procedure call link register. */ + + current_el = rt_hw_get_current_el(); + + if(current_el == 3) + { + *(--stk) = INITIAL_SPSR_EL3; + } + else if(current_el == 2) + { + *(--stk) = INITIAL_SPSR_EL2; + } + else + { + *(--stk) = INITIAL_SPSR_EL1; + } + + *(--stk) = ( rt_ubase_t ) tentry; /* Exception return address. */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} diff --git a/libcpu/aarch64/cortex-a57/trap.c b/libcpu/aarch64/cortex-a57/trap.c new file mode 100644 index 0000000000..d93aa18fd6 --- /dev/null +++ b/libcpu/aarch64/cortex-a57/trap.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Date Author Notes + * 2018-10-06 ZhaoXiaowei the first version + */ + +#include +#include + +#include "interrupt.h" +#include "armv8.h" + +extern struct rt_thread *rt_current_thread; +#ifdef RT_USING_FINSH +extern long list_thread(void); +#endif + +/** + * this function will show registers of CPU + * + * @param regs the registers point + */ +void rt_hw_show_register(struct rt_hw_exp_stack *regs) +{ + rt_kprintf("Execption:\n"); + rt_kprintf("r00:0x%16.16lx r01:0x%16.16lx r02:0x%16.16lx r03:0x%16.16lx\n", regs->x0, regs->x1, regs->x2, regs->x3); + rt_kprintf("r04:0x%16.16lx r05:0x%16.16lx r06:0x%16.16lx r07:0x%16.16lx\n", regs->x4, regs->x5, regs->x6, regs->x7); + rt_kprintf("r08:0x%16.16lx r09:0x%16.16lx r10:0x%16.16lx r11:0x%16.16lx\n", regs->x8, regs->x9, regs->x10, regs->x11); + rt_kprintf("r12:0x%16.16lx r13:0x%16.16lx r14:0x%16.16lx r15:0x%16.16lx\n", regs->x12, regs->x13, regs->x14, regs->x15); + rt_kprintf("r16:0x%16.16lx r17:0x%16.16lx r18:0x%16.16lx r19:0x%16.16lx\n", regs->x16, regs->x17, regs->x18, regs->x19); + rt_kprintf("r20:0x%16.16lx r21:0x%16.16lx r22:0x%16.16lx r23:0x%16.16lx\n", regs->x20, regs->x21, regs->x22, regs->x23); + rt_kprintf("r24:0x%16.16lx r25:0x%16.16lx r26:0x%16.16lx r27:0x%16.16lx\n", regs->x24, regs->x25, regs->x26, regs->x27); + rt_kprintf("r28:0x%16.16lx r29:0x%16.16lx r30:0x%16.16lx\n", regs->x28, regs->x29, regs->x30); + rt_kprintf("spsr:0x%16.16lx\n", regs->spsr); + rt_kprintf("return pc:0x%16.16lx\n", regs->pc); +} + +/** + * When comes across an instruction which it cannot handle, + * it takes the undefined instruction trap. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_error(struct rt_hw_exp_stack *regs) +{ + rt_kprintf("error exception:\n"); + rt_hw_show_register(regs); +#ifdef RT_USING_FINSH + list_thread(); +#endif + rt_hw_cpu_shutdown(); +} + +#define GIC_ACK_INTID_MASK 0x000003ff + +int rt_hw_interrupt_get_irq(void); +void rt_hw_interrupt_ack(int fiq_irq); + +void rt_hw_trap_irq(void) +{ + void *param; + int ir; + rt_isr_handler_t isr_func; + extern struct rt_irq_desc isr_table[]; + + ir = rt_hw_interrupt_get_irq(); + if (ir == 1023) + { + /* Spurious interrupt */ + return; + } + + /* get interrupt service routine */ + isr_func = isr_table[ir].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[ir].counter++; +#endif + if (isr_func) + { + /* Interrupt for myself. */ + param = isr_table[ir].param; + /* turn to interrupt service routine */ + isr_func(ir, param); + } + + /* end of interrupt */ + rt_hw_interrupt_ack(ir); + +} + +void rt_hw_trap_fiq(void) +{ +} -- cgit v1.3.1