diff options
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/aarch64/SConscript | 3 | ||||
| -rw-r--r-- | libcpu/aarch64/common/SConscript | 24 | ||||
| -rw-r--r-- | libcpu/aarch64/common/armv8.h (renamed from libcpu/aarch64/cortex-a53/armv8.h) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/cache.S (renamed from libcpu/aarch64/cortex-a53/cache.S) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/context_gcc.S (renamed from libcpu/aarch64/cortex-a53/context_gcc.S) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/cp15.h (renamed from libcpu/aarch64/cortex-a53/cp15.h) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/cpu.c (renamed from libcpu/aarch64/cortex-a53/cpu.c) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/cpu_gcc.S (renamed from libcpu/aarch64/cortex-a53/cpu_gcc.S) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/gic/SConscript | 24 | ||||
| -rw-r--r-- | libcpu/aarch64/common/gic/gic_pl400.c | 368 | ||||
| -rw-r--r-- | libcpu/aarch64/common/gic/gic_pl400.h | 35 | ||||
| -rw-r--r-- | libcpu/aarch64/common/mmu.c (renamed from libcpu/aarch64/cortex-a53/mmu.c) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/mmu.h (renamed from libcpu/aarch64/cortex-a53/mmu.h) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/startup_gcc.S (renamed from libcpu/aarch64/cortex-a53/startup_gcc.S) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/common/vector_gcc.S (renamed from libcpu/aarch64/cortex-a53/vector_gcc.S) | 0 | ||||
| -rw-r--r-- | libcpu/aarch64/cortex-a53/SConscript | 15 | ||||
| -rw-r--r-- | libcpu/aarch64/cortex-a53/interrupt.h | 6 | ||||
| -rw-r--r-- | libcpu/aarch64/cortex-a57/SConscript | 13 | ||||
| -rw-r--r-- | libcpu/aarch64/cortex-a57/entry_point.S | 111 | ||||
| -rw-r--r-- | libcpu/aarch64/cortex-a57/interrupt.c | 73 | ||||
| -rw-r--r-- | libcpu/aarch64/cortex-a57/interrupt.h | 27 | ||||
| -rw-r--r-- | libcpu/aarch64/cortex-a57/stack.c | 90 | ||||
| -rw-r--r-- | libcpu/aarch64/cortex-a57/trap.c | 98 |
23 files changed, 874 insertions, 13 deletions
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/cortex-a53/armv8.h b/libcpu/aarch64/common/armv8.h index 4350890544..4350890544 100644 --- a/libcpu/aarch64/cortex-a53/armv8.h +++ b/libcpu/aarch64/common/armv8.h diff --git a/libcpu/aarch64/cortex-a53/cache.S b/libcpu/aarch64/common/cache.S index 7f295a2b02..7f295a2b02 100644 --- a/libcpu/aarch64/cortex-a53/cache.S +++ b/libcpu/aarch64/common/cache.S diff --git a/libcpu/aarch64/cortex-a53/context_gcc.S b/libcpu/aarch64/common/context_gcc.S index 934db7ed84..934db7ed84 100644 --- a/libcpu/aarch64/cortex-a53/context_gcc.S +++ b/libcpu/aarch64/common/context_gcc.S diff --git a/libcpu/aarch64/cortex-a53/cp15.h b/libcpu/aarch64/common/cp15.h index f3ffd6f857..f3ffd6f857 100644 --- a/libcpu/aarch64/cortex-a53/cp15.h +++ b/libcpu/aarch64/common/cp15.h diff --git a/libcpu/aarch64/cortex-a53/cpu.c b/libcpu/aarch64/common/cpu.c index 962a53a071..962a53a071 100644 --- a/libcpu/aarch64/cortex-a53/cpu.c +++ b/libcpu/aarch64/common/cpu.c diff --git a/libcpu/aarch64/cortex-a53/cpu_gcc.S b/libcpu/aarch64/common/cpu_gcc.S index b8c8b8768c..b8c8b8768c 100644 --- a/libcpu/aarch64/cortex-a53/cpu_gcc.S +++ b/libcpu/aarch64/common/cpu_gcc.S 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 <stdint.h> + +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/cortex-a53/mmu.c b/libcpu/aarch64/common/mmu.c index b799143084..b799143084 100644 --- a/libcpu/aarch64/cortex-a53/mmu.c +++ b/libcpu/aarch64/common/mmu.c diff --git a/libcpu/aarch64/cortex-a53/mmu.h b/libcpu/aarch64/common/mmu.h index 6a66472c79..6a66472c79 100644 --- a/libcpu/aarch64/cortex-a53/mmu.h +++ b/libcpu/aarch64/common/mmu.h diff --git a/libcpu/aarch64/cortex-a53/startup_gcc.S b/libcpu/aarch64/common/startup_gcc.S index ea4268148c..ea4268148c 100644 --- a/libcpu/aarch64/cortex-a53/startup_gcc.S +++ b/libcpu/aarch64/common/startup_gcc.S diff --git a/libcpu/aarch64/cortex-a53/vector_gcc.S b/libcpu/aarch64/common/vector_gcc.S index fc88cce7f8..fc88cce7f8 100644 --- a/libcpu/aarch64/cortex-a53/vector_gcc.S +++ b/libcpu/aarch64/common/vector_gcc.S 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/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-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 <rthw.h> +#include <rtthread.h> +#include <gic_pl400.h> +#include <board.h> +#include <armv8.h> + +#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 <rthw.h> +#include <board.h> + +#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 <rtthread.h> +#include <board.h> + +#include <armv8.h> + +#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 <rtthread.h> +#include <rthw.h> + +#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) +{ +} |
