qinwei2004 commented on code in PR #6478: URL: https://github.com/apache/incubator-nuttx/pull/6478#discussion_r920691903
########## arch/arm64/src/common/arm64_arch.h: ########## @@ -0,0 +1,569 @@ +/**************************************************************************** + * arch/arm64/src/common/arm64_arch.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef ___ARCH_ARM64_SRC_COMMON_ARM64_ARCH_H +#define ___ARCH_ARM64_SRC_COMMON_ARM64_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/* Unsigned integer with bit position n set (signed in + * assembly language). + */ +#ifndef __ASSEMBLY__ + #include <stdint.h> + #include <inttypes.h> + #define BIT(n) (UINT32_C(1) << (n)) + #define BIT64(n) (UINT64_C(1) << (n)) +#else + #define BIT(n) ((1UL) << (n)) + #define BIT64(n) ((1ULL) << (n)) +#endif + +/* Bit mask with bits 0 through n-1 (inclusive) set, + * or 0 if n is 0. + */ +#define BIT_MASK(n) (BIT(n) - 1) +#define BIT64_MASK(n) (BIT64(n) - 1ULL) + +#define DAIFSET_FIQ_BIT BIT(0) +#define DAIFSET_IRQ_BIT BIT(1) +#define DAIFSET_ABT_BIT BIT(2) +#define DAIFSET_DBG_BIT BIT(3) + +#define DAIFCLR_FIQ_BIT BIT(0) +#define DAIFCLR_IRQ_BIT BIT(1) +#define DAIFCLR_ABT_BIT BIT(2) +#define DAIFCLR_DBG_BIT BIT(3) + +#define DAIF_FIQ_BIT BIT(6) +#define DAIF_IRQ_BIT BIT(7) +#define DAIF_ABT_BIT BIT(8) +#define DAIF_DBG_BIT BIT(9) + +#define DAIF_MASK (0xf << 6) + +/* Arm® Architecture Registers Armv8, for Armv8-A architecture profile + * ( DDI 0595, ID121321 ), defined: + * + * SCTLR_EL1: System Control Register (EL1) + * SCTLR_EL2: System Control Register (EL2) + * SCTLR_EL3: System Control Register (EL3) + * + */ + +#define SCTLR_EL3_RES1 (BIT(29) | BIT(28) | BIT(23) | \ + BIT(22) | BIT(18) | BIT(16) | \ + BIT(11) | BIT(5) | BIT(4)) + +#define SCTLR_EL2_RES1 (BIT(29) | BIT(28) | BIT(23) | \ + BIT(22) | BIT(18) | BIT(16) | \ + BIT(11) | BIT(5) | BIT(4)) + +#define SCTLR_EL1_RES1 (BIT(29) | BIT(28) | BIT(23) | \ + BIT(22) | BIT(20) | BIT(11)) + +#define SCTLR_M_BIT BIT(0) +#define SCTLR_A_BIT BIT(1) +#define SCTLR_C_BIT BIT(2) +#define SCTLR_SA_BIT BIT(3) +#define SCTLR_I_BIT BIT(12) + +/* SPSR M[3:0] define + * + * Arm® Architecture Registers Armv8, for Armv8-A architecture profile + * ( DDI 0595, ID121321 ), defined: + * SPSR_EL1: Saved Program Status Register (EL1) + * SPSR_EL2: Saved Program Status Register (EL2) + * SPSR_EL3: Saved Program Status Register (EL3) + * + * reference to Programmer’s Guide for ARMv8-A + * (ARM DEN0024A, ID050815 ), 4.1.2 Stack pointer + * + * The T suffix, indicates use of the SP_EL0 stack pointer. + * The H suffix, indicates use of the SP_ELx stack pointer. + * + */ + +#define SPSR_DAIF_SHIFT (6) +#define SPSR_DAIF_MASK (0xf << SPSR_DAIF_SHIFT) + +#define SPSR_MODE_EL0T (0x0) +#define SPSR_MODE_EL1T (0x4) +#define SPSR_MODE_EL1H (0x5) +#define SPSR_MODE_EL2T (0x8) +#define SPSR_MODE_EL2H (0x9) +#define SPSR_MODE_MASK (0xf) + +/* CurrentEL: Current Exception Level */ + +#define MODE_EL_SHIFT (0x2) +#define MODE_EL_MASK (0x3) + +#define MODE_EL3 (0x3) +#define MODE_EL2 (0x2) +#define MODE_EL1 (0x1) +#define MODE_EL0 (0x0) + +/* struct arm64_boot_params member offset for assembly code + * struct is defined at arm64_cpustart.c + */ + +#define BOOT_PARAM_MPID 0 +#define BOOT_PARAM_SP 8 + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STRINGIFY(x) #x +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/* define MAX(a, b)/MIN(a, b) + * The larger/smaller value between a and b. + * Arguments are evaluated twice. + */ +#ifndef MAX +# define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +# define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#define GET_EL(mode) (((mode) >> MODE_EL_SHIFT) & MODE_EL_MASK) + +/* MPIDR_EL1, Multiprocessor Affinity Register */ + +#define MPIDR_AFFLVL_MASK (0xff) + +#define MPIDR_AFF0_SHIFT (0) +#define MPIDR_AFF1_SHIFT (8) +#define MPIDR_AFF2_SHIFT (16) +#define MPIDR_AFF3_SHIFT (32) + +#define MPIDR_AFFLVL(mpidr, aff_level) \ + (((mpidr) >> MPIDR_AFF ## aff_level ## _SHIFT) & MPIDR_AFFLVL_MASK) + +#define GET_MPIDR() read_sysreg(mpidr_el1) +#define MPIDR_TO_CORE(mpidr) MPIDR_AFFLVL((mpidr), 0) +#define IS_PRIMARY_CORE() (!MPIDR_TO_CORE(GET_MPIDR())) + +/* System register interface to GICv3 */ + +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_SGI1R S3_0_C12_C11_5 +#define ICC_SRE_EL1 S3_0_C12_C12_5 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_PMR_EL1 S3_0_C4_C6_0 +#define ICC_RPR_EL1 S3_0_C12_C11_3 +#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7 +#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6 +#define ICC_HPPIR0_EL1 S3_0_C12_C8_2 +#define ICC_HPPIR1_EL1 S3_0_C12_C12_2 +#define ICC_IAR0_EL1 S3_0_C12_C8_0 +#define ICC_IAR1_EL1 S3_0_C12_C12_0 +#define ICC_EOIR0_EL1 S3_0_C12_C8_1 +#define ICC_EOIR1_EL1 S3_0_C12_C12_1 +#define ICC_SGI0R_EL1 S3_0_C12_C11_7 + +/* register constants */ +#define ICC_SRE_ELX_SRE_BIT BIT(0) +#define ICC_SRE_ELX_DFB_BIT BIT(1) +#define ICC_SRE_ELX_DIB_BIT BIT(2) +#define ICC_SRE_EL3_EN_BIT BIT(3) + +/* ICC SGI macros */ +#define SGIR_TGT_MASK (0xffff) +#define SGIR_AFF1_SHIFT (16) +#define SGIR_AFF2_SHIFT (32) +#define SGIR_AFF3_SHIFT (48) +#define SGIR_AFF_MASK (0xf) +#define SGIR_INTID_SHIFT (24) +#define SGIR_INTID_MASK (0xf) +#define SGIR_IRM_SHIFT (40) +#define SGIR_IRM_MASK (0x1) +#define SGIR_IRM_TO_AFF (0) +#define SGIR_IRM_TO_ALL (1) + +#define GICV3_SGIR_VALUE(_aff3, _aff2, _aff1, _intid, _irm, _tgt) \ + ((((uint64_t)(_aff3) & SGIR_AFF_MASK) << SGIR_AFF3_SHIFT) | \ + (((uint64_t)(_irm) & SGIR_IRM_MASK) << SGIR_IRM_SHIFT) | \ + (((uint64_t)(_aff2) & SGIR_AFF_MASK) << SGIR_AFF2_SHIFT) | \ + (((_intid) & SGIR_INTID_MASK) << SGIR_INTID_SHIFT) | \ + (((_aff1) & SGIR_AFF_MASK) << SGIR_AFF1_SHIFT) | \ + ((_tgt) & SGIR_TGT_MASK)) + +/* CPTR_EL2, Architectural Feature Trap Register (EL2) */ + +#define CPTR_EZ_BIT BIT(8) +#define CPTR_TFP_BIT BIT(10) +#define CPTR_TTA_BIT BIT(20) +#define CPTR_TCPAC_BIT BIT(31) +#define CPTR_EL2_RES1 BIT(13) | BIT(12) | BIT(9) | (0xff) + +/* CPACR_EL1, Architectural Feature Access Control Register */ +#define CPACR_EL1_FPEN_NOTRAP (0x3 << 20) + +/* SCR_EL3, Secure Configuration Register */ +#define SCR_NS_BIT BIT(0) +#define SCR_IRQ_BIT BIT(1) +#define SCR_FIQ_BIT BIT(2) +#define SCR_EA_BIT BIT(3) +#define SCR_SMD_BIT BIT(7) +#define SCR_HCE_BIT BIT(8) +#define SCR_RW_BIT BIT(10) +#define SCR_ST_BIT BIT(11) +#define SCR_RES1 (BIT(4) | BIT(5)) + +/* HCR_EL2, Hypervisor Configuration Register */ + +#define HCR_FMO_BIT BIT(3) +#define HCR_IMO_BIT BIT(4) +#define HCR_AMO_BIT BIT(5) +#define HCR_RW_BIT BIT(31) + +/* CNTHCTL_EL2 bits definitions */ + +#define CNTHCTL_EL2_EL1PCEN_EN BIT(1) +#define CNTHCTL_EL2_EL1PCTEN_EN BIT(0) + +/* CNTV_CVAL, Counter-timer Virtual Timer CompareValue register + * CNTV_CTL, Counter-timer Virtual Timer Control register + */ + +#define CNTV_CTL_ENABLE_BIT BIT(0) +#define CNTV_CTL_IMASK_BIT BIT(1) + +/* Maximum numbers of translation tables + * This option specifies the maximum numbers of translation tables + * excluding the base translation table. Based on this, translation + * tables are allocated at compile time and used at runtime as needed. + * If the runtime need exceeds preallocated numbers of translation + * tables, it will result in assert. Number of translation tables + * required is decided based on how many discrete memory regions + * (both normal and device memory) are present on given platform and + * how much granularity is required while assigning attributes + * to these memory regions. + */ + +#define CONFIG_MAX_XLAT_TABLES 7 + +/* Virtual address space size + * Allows choosing one of multiple possible virtual address + * space sizes. The level of translation table is determined by + * a combination of page size and virtual address space size. + * + * The choice could be: 32, 36, 42, 48 + */ + +#define CONFIG_ARM64_VA_BITS 36 + +/* Physical address space size + * Choose the maximum physical address range that the kernel will support. + * + * The choice could be: 32, 36, 42, 48 + */ + +#define CONFIG_ARM64_PA_BITS 36 + +#define L1_CACHE_SHIFT (6) +#define L1_CACHE_BYTES BIT(L1_CACHE_SHIFT) + +/**************************************************************************** + * Type Declarations + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FPU + +/**************************************************************************** + * armv8 fpu registers and context + ****************************************************************************/ + +struct fpu_reg +{ + __int128 q[32]; + uint32_t fpsr; + uint32_t fpcr; + uint64_t fpu_trap; +}; + +#endif + +/**************************************************************************** + * Registers and exception context + ****************************************************************************/ + +struct regs_context +{ + uint64_t regs[31]; /* x0~x30 */ + uint64_t sp_elx; + uint64_t elr; + uint64_t spsr; + uint64_t sp_el0; + uint64_t exe_depth; + uint64_t tpidr_el0; + uint64_t tpidr_el1; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* See Arm® Architecture Reference Manual + * ARM DDI 0487E.a C6.2.81 + */ + +static inline void __DSB(void) +{ + __asm__ volatile ("dsb sy" : : : "memory"); +} + +/* See Arm® Architecture Reference Manual + * ARM DDI 0487E.a C6.2.79 + */ + +static inline void __DMB(void) +{ + __asm__ volatile ("dmb sy" : : : "memory"); +} + +/* See Arm® Architecture Reference Manual + * ARM DDI 0487E.a C6.2.96 + */ + +static inline void __ISB(void) +{ + __asm__ volatile ("isb" : : : "memory"); +} Review Comment: I perfer to add prefix ARM64_ to define. please check ########## arch/arm64/src/common/arm64_arch_timer.c: ########## @@ -0,0 +1,254 @@ +/**************************************************************************** + * arch/arm64/src/common/arm64_arch_timer.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <debug.h> +#include <assert.h> + +#include <nuttx/arch.h> +#include <arch/irq.h> +#include <arch/chip/chip.h> +#include <nuttx/spinlock.h> + +#include "arm64_arch.h" +#include "arm64_internal.h" +#include "arm64_gic.h" +#include "arm64_arch_timer.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +#define MIN_DELAY (1000) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint64_t last_cycle; +static uint64_t cycle_per_tick; +static uint32_t arch_timer_rate; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline void arm64_arch_timer_set_compare(uint64_t value) +{ + write_sysreg(value, cntv_cval_el0); +} + +static inline void arm64_arch_timer_enable(unsigned char enable) +{ + uint64_t value; + + value = read_sysreg(cntv_ctl_el0); + + if (enable) + { + value |= CNTV_CTL_ENABLE_BIT; + } + else + { + value &= ~CNTV_CTL_ENABLE_BIT; + } + + write_sysreg(value, cntv_ctl_el0); +} + +static inline void arm64_arch_timer_set_irq_mask(bool mask) +{ + uint64_t value; + + value = read_sysreg(cntv_ctl_el0); + + if (mask) + { + value |= CNTV_CTL_IMASK_BIT; + } + else + { + value &= ~CNTV_CTL_IMASK_BIT; + } + + write_sysreg(value, cntv_ctl_el0); +} + +static inline uint64_t arm64_arch_timer_count(void) +{ + return read_sysreg(cntvct_el0); +} + +static inline uint32_t arm64_arch_timer_get_cntfrq(void) +{ + return read_sysreg(cntfrq_el0); +} + +#ifdef CONFIG_SCHED_TICKLESS +static int arm64_arch_timer_compare_isr(int irq, void *regs, void *arg) +{ + irqstate_t flags; + uint64_t curr_cycle; + uint32_t delta_ticks; + + UNUSED(regs); + UNUSED(arg); + + flags = spin_lock_irqsave(&g_arch_timer_lock); + + curr_cycle = arm64_arch_timer_count(); + delta_ticks = (uint32_t)((curr_cycle - last_cycle) / cycle_per_tick); + + last_cycle += delta_ticks * cycle_per_tick; + + arm_arch_timer_set_irq_mask(true); + + spin_unlock_irqrestore(&g_arch_timer_lock, flags); + + nxsched_process_timer(); + return OK; +} + +#else + +static int arm64_arch_timer_compare_isr(int irq, void *regs, void *arg) +{ + uint64_t curr_cycle; + uint32_t delta_ticks; + uint64_t next_cycle; + + UNUSED(irq); + UNUSED(regs); + UNUSED(arg); + + curr_cycle = arm64_arch_timer_count(); + delta_ticks = (uint32_t)((curr_cycle - last_cycle) / cycle_per_tick); + + last_cycle += delta_ticks * cycle_per_tick; + + next_cycle = last_cycle + cycle_per_tick; + + if ((uint64_t)(next_cycle - curr_cycle) < MIN_DELAY) + { + next_cycle += cycle_per_tick; + } + + arm64_arch_timer_set_compare(next_cycle); + arm64_arch_timer_set_irq_mask(false); + + nxsched_process_timer(); + return OK; +} + +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_SMP +/* Notes: + * + * The origin design for ARMv8-A timer is assigned private timer to + * every PE(CPU core), the ARM_ARCH_TIMER_IRQ is a PPI so it's + * should be enable at every core. + * + * But for NuttX, it's design only for primary core to handle timer + * interrupt and call nxsched_process_timer at timer tick mode. + * So we need only enable timer for primary core + * + * IMX6 use GPT which is a SPI rather than generic timer to handle + * timer interrupt + */ + +void arm64_smp_timer_init(void) +{ + uint64_t curr_cycle; + + /* set the initial status of timer0 of each secondary core */ + + curr_cycle = arm64_arch_timer_count(); + + arm64_arch_timer_set_compare(curr_cycle + cycle_per_tick); + arm64_arch_timer_enable(true); + up_enable_irq(ARM_ARCH_TIMER_IRQ); + arm64_arch_timer_set_irq_mask(false); +} + +#endif + +uint64_t arm64_counter_read(void) +{ + return arm64_arch_timer_count(); +} + +void arm64_timer_delay(long mini_sec) +{ + unsigned int timeout; + volatile unsigned int new_counter; Review Comment: Oh, arm64_timer_delay is a very early version to used at arm64_assert.c, only for debug propose I think I perfer to use up_mdelay instead Thanks for check -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org