diff options
| author | Man, Jianting (Meco) <[email protected]> | 2021-08-17 16:56:10 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-08-17 16:56:10 -0500 |
| commit | 3e6578916f892e4456d9dff4bbd44590a0cb4bc8 (patch) | |
| tree | b98d9fe601ce62e17b37f5b971f0cc9f965fa0e3 /libcpu/aarch64/common | |
| parent | 37a9231e6219b94f7cde8bdea9251e260c4bed18 (diff) | |
| parent | 196f340e5d845efd005b57a2089e0642266a79be (diff) | |
Merge branch 'master' into security
Diffstat (limited to 'libcpu/aarch64/common')
| -rw-r--r-- | libcpu/aarch64/common/armv8.h | 80 | ||||
| -rw-r--r-- | libcpu/aarch64/common/cp15.h | 6 | ||||
| -rw-r--r-- | libcpu/aarch64/common/cpu.c | 2 | ||||
| -rw-r--r-- | libcpu/aarch64/common/gic/SConscript | 6 | ||||
| -rw-r--r-- | libcpu/aarch64/common/gic/gic_pl390.c | 273 | ||||
| -rw-r--r-- | libcpu/aarch64/common/gic/gic_pl390.h | 27 | ||||
| -rw-r--r-- | libcpu/aarch64/common/gic/gic_pl400.c | 2 | ||||
| -rw-r--r-- | libcpu/aarch64/common/gic/gic_pl400.h | 2 | ||||
| -rw-r--r-- | libcpu/aarch64/common/mmu.c | 32 | ||||
| -rw-r--r-- | libcpu/aarch64/common/mmu.h | 2 |
10 files changed, 369 insertions, 63 deletions
diff --git a/libcpu/aarch64/common/armv8.h b/libcpu/aarch64/common/armv8.h index 4350890544..77fb4de8a2 100644 --- a/libcpu/aarch64/common/armv8.h +++ b/libcpu/aarch64/common/armv8.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -14,47 +14,47 @@ /* 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; + 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 ) +#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); diff --git a/libcpu/aarch64/common/cp15.h b/libcpu/aarch64/common/cp15.h index f3ffd6f857..e6d8626ab9 100644 --- a/libcpu/aarch64/common/cp15.h +++ b/libcpu/aarch64/common/cp15.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -55,7 +55,7 @@ static inline void send_ipi_msg(int cpu, int ipi_vector) static inline void setup_bootstrap_addr(int cpu, int addr) { - CORE_MAILBOX3_SET(cpu) = addr; + CORE_MAILBOX3_SET(cpu) = addr; } static inline void enable_cpu_ipi_intr(int cpu) @@ -65,7 +65,7 @@ static inline void enable_cpu_ipi_intr(int cpu) static inline void enable_cpu_timer_intr(int cpu) { - CORETIMER_INTCTL(cpu) = 0x8; + CORETIMER_INTCTL(cpu) = 0x8; } static inline void enable_cntv(void) diff --git a/libcpu/aarch64/common/cpu.c b/libcpu/aarch64/common/cpu.c index 84d3df2e8a..66b540a5e5 100644 --- a/libcpu/aarch64/common/cpu.c +++ b/libcpu/aarch64/common/cpu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/libcpu/aarch64/common/gic/SConscript b/libcpu/aarch64/common/gic/SConscript index b114ba7678..28daac87ff 100644 --- a/libcpu/aarch64/common/gic/SConscript +++ b/libcpu/aarch64/common/gic/SConscript @@ -5,6 +5,10 @@ from building import * cwd = GetCurrentDir() CPPPATH = [cwd] +gic390_group = Split(''' +gic_pl390.c +''') + gic400_group = Split(''' gic_pl400.c ''') @@ -14,6 +18,8 @@ gic_pl500.c ''') src = () +if GetDepend('BSP_USING_GIC390'): + src = gic390_group if GetDepend('BSP_USING_GIC400'): src = gic400_group if GetDepend('BSP_USING_GIC500'): diff --git a/libcpu/aarch64/common/gic/gic_pl390.c b/libcpu/aarch64/common/gic/gic_pl390.c new file mode 100644 index 0000000000..a8e3b10d94 --- /dev/null +++ b/libcpu/aarch64/common/gic/gic_pl390.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-07-31 GuEe-GUI the first version + */ +#include <rtthread.h> + +#include "gic_pl390.h" + +#define BIT(n) (1ul<<(n)) +#define MASK(n) (BIT(n)-1ul) + +#define IRQ_REG(IRQ) ((IRQ) / 32) +#define IRQ_BIT(IRQ) BIT((IRQ) % 32) +#define IRQ_MASK MASK(10) +#define IRQ_SET_ALL 0xffffffff +#define IS_IRQ_VALID(X) (((X)&IRQ_MASK) < GIC390_SPECIAL_IRQ_START) + +#define TARGET_CPU_ALLINT(CPU) \ +( \ + (((CPU) & 0xff) << 0 ) | \ + (((CPU) & 0xff) << 8 ) | \ + (((CPU) & 0xff) << 16) | \ + (((CPU) & 0xff) << 24) \ +) +#define CPU(X) (1<<(X)) +#define TARGET_CPU0_ALLINT TARGET_CPU_ALLINT(CPU(0)) + +/* memory map for GIC distributor */ +struct gic_dist_map +{ + rt_uint32_t enable; /* 0x000 */ + rt_uint32_t ic_type; /* 0x004 */ + rt_uint32_t dist_ident; /* 0x008 */ + rt_uint32_t res1[29]; /* [0x00C, 0x080) */ + + rt_uint32_t security[32]; /* [0x080, 0x100) */ + + rt_uint32_t enable_set[32]; /* [0x100, 0x180) */ + rt_uint32_t enable_clr[32]; /* [0x180, 0x200) */ + rt_uint32_t pending_set[32]; /* [0x200, 0x280) */ + rt_uint32_t pending_clr[32]; /* [0x280, 0x300) */ + rt_uint32_t active[32]; /* [0x300, 0x380) */ + rt_uint32_t res2[32]; /* [0x380, 0x400) */ + + rt_uint32_t priority[255]; /* [0x400, 0x7FC) */ + rt_uint32_t res3; /* 0x7FC */ + + rt_uint32_t targets[255]; /* [0x800, 0xBFC) */ + rt_uint32_t res4; /* 0xBFC */ + + rt_uint32_t config[64]; /* [0xC00, 0xD00) */ + + rt_uint32_t spi[32]; /* [0xD00, 0xD80) */ + rt_uint32_t res5[20]; /* [0xD80, 0xDD0) */ + rt_uint32_t res6; /* 0xDD0 */ + rt_uint32_t legacy_int; /* 0xDD4 */ + rt_uint32_t res7[2]; /* [0xDD8, 0xDE0) */ + rt_uint32_t match_d; /* 0xDE0 */ + rt_uint32_t enable_d; /* 0xDE4 */ + rt_uint32_t res8[70]; /* [0xDE8, 0xF00) */ + + rt_uint32_t sgi_control; /* 0xF00 */ + rt_uint32_t res9[3]; /* [0xF04, 0xF10) */ + rt_uint32_t sgi_pending_clr[4]; /* [0xF10, 0xF20) */ + rt_uint32_t res10[40]; /* [0xF20, 0xFC0) */ + + rt_uint32_t periph_id[12]; /* [0xFC0, 0xFF0) */ + rt_uint32_t component_id[4]; /* [0xFF0, 0xFFF] */ +}; + +/* memory map for GIC CPU interface */ +struct gic_cpu_iface_map +{ + rt_uint32_t icontrol; /* 0x000 */ + rt_uint32_t pri_msk_c; /* 0x004 */ + rt_uint32_t pb_c; /* 0x008 */ + rt_uint32_t int_ack; /* 0x00C */ + rt_uint32_t eoi; /* 0x010 */ + rt_uint32_t run_priority; /* 0x014 */ + rt_uint32_t hi_pend; /* 0x018 */ + rt_uint32_t ns_alias_bp_c; /* 0x01C */ + rt_uint32_t ns_alias_ack; /* 0x020 GIC400 only */ + rt_uint32_t ns_alias_eoi; /* 0x024 GIC400 only */ + rt_uint32_t ns_alias_hi_pend; /* 0x028 GIC400 only */ + + rt_uint32_t res1[5]; /* [0x02C, 0x040) */ + + rt_uint32_t integ_en_c; /* 0x040 PL390 only */ + rt_uint32_t interrupt_out; /* 0x044 PL390 only */ + rt_uint32_t res2[2]; /* [0x048, 0x050) */ + + rt_uint32_t match_c; /* 0x050 PL390 only */ + rt_uint32_t enable_c; /* 0x054 PL390 only */ + + rt_uint32_t res3[30]; /* [0x058, 0x0FC) */ + rt_uint32_t active_priority[4]; /* [0x0D0, 0xDC] GIC400 only */ + rt_uint32_t ns_active_priority[4]; /* [0xE0,0xEC] GIC400 only */ + rt_uint32_t res4[3]; + + rt_uint32_t cpu_if_ident; /* 0x0FC */ + rt_uint32_t res5[948]; /* [0x100. 0xFC0) */ + + rt_uint32_t periph_id[8]; /* [0xFC0, 9xFF0) PL390 only */ + rt_uint32_t component_id[4]; /* [0xFF0, 0xFFF] PL390 only */ +}; + +volatile struct gic_dist_map *gic_dist = + (volatile struct gic_dist_map*)(GIC_PL390_DISTRIBUTOR_PPTR); + +volatile struct gic_cpu_iface_map *gic_cpuiface = + (volatile struct gic_cpu_iface_map*)(GIC_PL390_CONTROLLER_PPTR); + +/* + * 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 rt_uint32_t active_irq = GIC390_IRQ_NONE; + +rt_inline int is_irq_edge_triggered(int irq) +{ + int word = irq / 16; + int bit = ((irq & 0xf) * 2); + + return !!(gic_dist->config[word] & BIT(bit + 1)); +} + +rt_inline void dist_pending_clr(int irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + gic_dist->pending_clr[word] = BIT(bit); +} + +rt_inline void dist_init(void) +{ + int i; + int nirqs = 32 * ((gic_dist->ic_type & 0x1f) + 1); + gic_dist->enable = 0; + + 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; + } + /* enable the int controller */ + gic_dist->enable = 1; +} + +rt_inline void cpu_iface_init(void) +{ + rt_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->pb_c = 0x00000003; + + while (((i = gic_cpuiface->int_ack) & IRQ_MASK) != GIC390_IRQ_NONE) + { + gic_cpuiface->eoi = i; + } + gic_cpuiface->icontrol = 0x1; +} + + +void arm_gic_irq_init(void) +{ + dist_init(); + cpu_iface_init(); +} + +int arm_gic_get_active_irq(void) +{ + int 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 = GIC390_IRQ_NONE; + } + + return irq; +} + +void arm_gic_mask(int irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + + gic_dist->enable_clr[word] = BIT(bit); +} + +void arm_gic_umask(int irq) +{ + int word = irq / 32; + int bit = irq & 0x1f; + gic_dist->enable_set[word] = BIT(bit); +} + +void arm_gic_ack(int 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 = GIC390_IRQ_NONE; +} + +int rt_hw_interrupt_get_irq(void) +{ + return arm_gic_get_active_irq(); +} + +void rt_hw_interrupt_ack(int fiq_irq) +{ + return arm_gic_ack(fiq_irq); +} + diff --git a/libcpu/aarch64/common/gic/gic_pl390.h b/libcpu/aarch64/common/gic/gic_pl390.h new file mode 100644 index 0000000000..7ea574967d --- /dev/null +++ b/libcpu/aarch64/common/gic/gic_pl390.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-07-31 GuEe-GUI the first version + */ + +#ifndef GIC_PL390_H__ +#define GIC_PL390_H__ + +#include <board.h> + +#define GIC390_SPECIAL_IRQ_START 1020 +#define GIC390_IRQ_NONE 1023 + +void arm_gic_irq_init(void); + +int arm_gic_get_active_irq(void); +void arm_gic_ack(int irq); + +void arm_gic_mask(int irq); +void arm_gic_umask(int irq); + +#endif diff --git a/libcpu/aarch64/common/gic/gic_pl400.c b/libcpu/aarch64/common/gic/gic_pl400.c index 1f4d868636..ec690a1cc6 100644 --- a/libcpu/aarch64/common/gic/gic_pl400.c +++ b/libcpu/aarch64/common/gic/gic_pl400.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/libcpu/aarch64/common/gic/gic_pl400.h b/libcpu/aarch64/common/gic/gic_pl400.h index fa20846ea2..9ca4835b9a 100644 --- a/libcpu/aarch64/common/gic/gic_pl400.h +++ b/libcpu/aarch64/common/gic/gic_pl400.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/libcpu/aarch64/common/mmu.c b/libcpu/aarch64/common/mmu.c index b799143084..2a41c4f813 100644 --- a/libcpu/aarch64/common/mmu.c +++ b/libcpu/aarch64/common/mmu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -52,7 +52,7 @@ void mmu_memset(char *dst, char v, size_t len) } static unsigned long __page_off = 0; -static unsigned long get_free_page(void) +static unsigned long get_free_page(void) { __page_off += 512; return (unsigned long)(main_tbl + __page_off); @@ -128,7 +128,7 @@ void mmu_enable(void) } -static int map_single_page_2M(unsigned long* lv0_tbl, unsigned long va, unsigned long pa, unsigned long attr) +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; @@ -136,22 +136,22 @@ static int map_single_page_2M(unsigned long* lv0_tbl, unsigned long va, unsigned unsigned long off; int level_shift = 39; - if (va & (0x200000UL - 1)) + if (va & (0x200000UL - 1)) { return MMU_MAP_ERROR_VANOTALIGN; } - if (pa & (0x200000UL - 1)) + if (pa & (0x200000UL - 1)) { return MMU_MAP_ERROR_PANOTALIGN; } - for (level = 0; level < 2; level++) + for (level = 0; level < 2; level++) { off = (va >> level_shift); off &= MMU_LEVEL_MASK; - if ((cur_lv_tbl[off] & 1) == 0) + if ((cur_lv_tbl[off] & 1) == 0) { page = get_free_page(); - if (!page) + if (!page) { return MMU_MAP_ERROR_NOPAGE; } @@ -159,7 +159,7 @@ static int map_single_page_2M(unsigned long* lv0_tbl, unsigned long va, unsigned cur_lv_tbl[off] = page | 0x3UL; } page = cur_lv_tbl[off]; - if (!(page & 0x2)) + if (!(page & 0x2)) { //is block! error! return MMU_MAP_ERROR_CONFLICT; @@ -239,8 +239,8 @@ static int level2shift(int 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) + + if (pte_type(pte) != PMD_TYPE_TABLE) { table = create_table(); set_table(pte, table); @@ -259,10 +259,10 @@ static void map_region(uint64_t virt, uint64_t phys, uint64_t size, uint64_t att int level = 0; addr = virt; - while (size) + while (size) { table = &main_tbl[0]; - for (level = 0; level < 4; level++) + for (level = 0; level < 4; level++) { block_shift = level2shift(level); idx = addr >> block_shift; @@ -270,7 +270,7 @@ static void map_region(uint64_t virt, uint64_t phys, uint64_t size, uint64_t att block_size = (uint64_t)(1L << block_shift); pte = table + idx; - if (size >= block_size && IS_ALIGNED(addr, block_size)) + if (size >= block_size && IS_ALIGNED(addr, block_size)) { attr &= 0xfff0000000000ffcUL; if(level != 3) @@ -298,7 +298,7 @@ void armv8_map(unsigned long va, unsigned long pa, unsigned long size, unsigned void rt_hw_dcache_enable(void) { - if (!(get_sctlr() & CR_M)) + if (!(get_sctlr() & CR_M)) { rt_kprintf("please init mmu!\n"); } @@ -364,4 +364,4 @@ void rt_hw_icache_invalidate_all(void) 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 index 6a66472c79..f3261c3a1d 100644 --- a/libcpu/aarch64/common/mmu.h +++ b/libcpu/aarch64/common/mmu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * |
