ARMv7 CPSR位图

ARMv7架构中的CPSR(Current Program Status Register)是32位的寄存器,用于存储处理器的当前状态信息,包括条件标志、中断禁止位、处理器模式等。

以下是CPSR寄存器中每个bit位的详细说明:


1. 条件标志位(Condition Flags)

这些标志位用于指示算术逻辑单元(ALU)操作的结果状态,支持条件执行指令。

Bit 位置 标志位 功能描述
31 N (Negative) 负数标志。如果运算结果为负数(补码表示),则N=1;否则N=0。
30 Z (Zero) 零标志。如果运算结果为0,则Z=1;否则Z=0。
29 C (Carry) 进位/借位标志:
- 加法操作:如果结果产生进位(无符号溢出),则C=1。
- 减法操作:如果发生借位(无符号下溢),则C=0。
- 移位操作:C保存最后一次移出的位。
28 V (Overflow) 溢出标志。如果带符号运算发生溢出(结果超出补码范围),则V=1。

2. 控制位(Control Bits)

这些位控制处理器的运行模式、中断屏蔽、指令集状态等。

Bit 位置 标志位 功能描述
27 Q (Cumulative Saturation) 饱和标志。仅在ARMv5TE及更高版本中存在,用于指示DSP指令(如饱和加法)是否发生溢出或饱和。
26:25 IT[1:0] Thumb-2指令集的If-Then条件执行状态位的一部分。与IT[7:2](见下文)共同决定条件执行的范围。
24 J (Jazelle) Jazelle模式标志:
- J=1:处理器处于Jazelle模式(执行Java字节码)。
- J=0:非Jazelle模式。
23:20 保留位 保留未使用,通常忽略。
19:16 GE[3:0] SIMD(单指令多数据)指令的“大于等于”标志。用于控制SIMD指令的并行比较操作。
15:10 IT[7:2] Thumb-2指令集的If-Then条件执行状态位。与IT[1:0](见上文)共同决定条件执行的范围(最多4条指令)。
9 E (Endianness) 大小端模式控制:
- E=1:大端模式(Big-Endian)。
- E=0:小端模式(Little-Endian)。
8 A (Asynchronous Abort Mask) 异步终止屏蔽位:
- A=1:禁止异步终止(如外部中断)。
- A=0:允许异步终止。
7 I (IRQ Mask) 中断屏蔽位(IRQ):
- I=1:禁止普通中断(IRQ)。
- I=0:允许普通中断(IRQ)。
6 F (FIQ Mask) 快速中断屏蔽位(FIQ):
- F=1:禁止快速中断(FIQ)。
- F=0:允许快速中断(FIQ)。
5 T (Thumb Mode) 指令集模式标志:
- T=1:处理器处于Thumb状态(16位指令集)。
- T=0:处理器处于ARM状态(32位指令集)。
J和T位组合决定具体模式
- J=0, T=0:ARM指令集。
- J=0, T=1:Thumb指令集。
- J=1, T=0:Jazelle指令集。
- J=1, T=1:ThumbEE指令集。

3. 处理器模式位(Mode Bits)

M[4:0](Bit 4~0)用于指定处理器当前的工作模式。ARMv7支持7种特权模式和用户模式。

M[4:0] 二进制值 处理器模式 描述
0b10000 16 User (usr) 非特权模式,用户程序运行在此模式。
0b10001 17 FIQ (fiq) 快速中断模式,处理高优先级中断。
0b10010 18 IRQ (irq) 通用中断模式,处理普通中断。
0b10011 19 Supervisor (svc) 管理模式,操作系统内核运行在此模式。
0b10111 23 Abort (abt) 数据访问中止模式,处理内存访问异常。
0b11011 27 Undefined (und) 未定义指令中止模式,处理未定义指令异常。
0b11111 31 System (sys) 特权模式,与User模式共享寄存器,但具有更高权限。
0b10110 22 Monitor (mon) ARMv7特有的监控模式,用于安全扩展(TrustZone)。

4. 其他功能位

Bit 位置 标志位 功能描述
27 Q (Cumulative Saturation) 仅在ARMv5TE及更高版本中存在,用于指示DSP指令的溢出或饱和状态。
26:25 IT[1:0] IT[7:2](Bit 15:10)共同构成Thumb-2的If-Then条件执行状态。
19:16 GE[3:0] 用于SIMD指令的并行比较操作,控制每组数据是否满足条件。

5. CPSR与APSR的区别

  • CPSR:所有模式下均可访问,包含完整的状态信息(条件标志、中断禁止位、模式位等)。
  • APSR (Application Program Status Register):用户模式下只能访问CPSR的部分位(如N、Z、C、V、Q、GE),用于应用程序编程。

6. 实际应用中的操作

  • 修改CPSR:通过MSR(Move to Status Register)和MRS(Move from Status Register)指令读写CPSR的特定字段。

    • 示例:
      MRS r0, CPSR   ; 将CPSR的值读入r0
      BIC r0, #0x80  ; 清除I位(允许IRQ中断)
      MSR CPSR, r0   ; 将修改后的值写回CPSR
      
  • 异常处理:当异常发生时,CPSR会被保存到对应的SPSR(Saved Program Status Register)中,以便异常返回后恢复状态。


总结

CPSR是ARMv7架构中最重要的状态寄存器,其32位字段涵盖了处理器的核心状态信息。理解每个bit的功能对于底层开发(如操作系统、驱动、中断处理)至关重要。开发人员可以通过操作CPSR的特定位来控制处理器行为,例如切换模式、屏蔽中断、执行条件指令等。

#ifndef ARM_H
#define ARM_H

#include <stdbool.h>
#include <stdint.h>
#include <util.h>

/* MIDR definitions */
#define MIDR_PRIMARY_PART_NUM_SHIFT	U(4)
#define MIDR_PRIMARY_PART_NUM_WIDTH	U(12)
#define MIDR_PRIMARY_PART_NUM_MASK	(BIT(MIDR_PRIMARY_PART_NUM_WIDTH) - 1)

#define MIDR_IMPLEMENTER_SHIFT		U(24)
#define MIDR_IMPLEMENTER_WIDTH		U(8)
#define MIDR_IMPLEMENTER_MASK		(BIT(MIDR_IMPLEMENTER_WIDTH) - 1)
#define MIDR_IMPLEMENTER_ARM		U(0x41)

#define MIDR_VARIANT_SHIFT		U(20)
#define MIDR_VARIANT_WIDTH		U(4)
#define MIDR_VARIANT_MASK		(BIT(MIDR_VARIANT_WIDTH) - 1)

#define MIDR_REVISION_SHIFT		U(0)
#define MIDR_REVISION_WIDTH		U(4)
#define MIDR_REVISION_MASK		(BIT(MIDR_REVISION_WIDTH) - 1)

#define CORTEX_A5_PART_NUM		U(0xC05)
#define CORTEX_A7_PART_NUM		U(0xC07)
#define CORTEX_A8_PART_NUM		U(0xC08)
#define CORTEX_A9_PART_NUM		U(0xC09)
#define CORTEX_A15_PART_NUM		U(0xC0F)
#define CORTEX_A17_PART_NUM		U(0xC0E)
#define CORTEX_A57_PART_NUM		U(0xD07)
#define CORTEX_A72_PART_NUM		U(0xD08)
#define CORTEX_A73_PART_NUM		U(0xD09)
#define CORTEX_A75_PART_NUM		U(0xD0A)
#define CORTEX_A65_PART_NUM		U(0xD06)
#define CORTEX_A65AE_PART_NUM		U(0xD43)
#define CORTEX_A76_PART_NUM		U(0xD0B)
#define CORTEX_A76AE_PART_NUM		U(0xD0E)
#define CORTEX_A77_PART_NUM		U(0xD0D)
#define CORTEX_A78_PART_NUM		U(0xD41)
#define CORTEX_A78AE_PART_NUM		U(0xD42)
#define CORTEX_A78C_PART_NUM		U(0xD4B)
#define CORTEX_A710_PART_NUM		U(0xD47)
#define CORTEX_X1_PART_NUM		U(0xD44)
#define CORTEX_X2_PART_NUM		U(0xD48)
#define NEOVERSE_E1_PART_NUM		U(0xD4A)
#define NEOVERSE_N1_PART_NUM		U(0xD0C)
#define NEOVERSE_N2_PART_NUM		U(0xD49)
#define NEOVERSE_V1_PART_NUM		U(0xD40)

/* MPIDR definitions */
#define MPIDR_AFFINITY_BITS	U(8)
#define MPIDR_AFFLVL_MASK	U(0xff)
#define MPIDR_AFF0_SHIFT	U(0)
#define MPIDR_AFF0_MASK		(MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)
#define MPIDR_AFF1_SHIFT	U(8)
#define MPIDR_AFF1_MASK		(MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT)
#define MPIDR_AFF2_SHIFT	U(16)
#define MPIDR_AFF2_MASK		(MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT)

#define MPIDR_MT_SHIFT		U(24)
#define MPIDR_MT_MASK		BIT(MPIDR_MT_SHIFT)

#define MPIDR_CPU_MASK		MPIDR_AFF0_MASK
#define MPIDR_CLUSTER_SHIFT	MPIDR_AFF1_SHIFT
#define MPIDR_CLUSTER_MASK	MPIDR_AFF1_MASK

#define MPIDR_AARCH32_AFF_MASK	(MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | \
				 MPIDR_AFF2_MASK)

/* CLIDR definitions */
#define CLIDR_LOUIS_SHIFT	U(21)
#define CLIDR_LOC_SHIFT		U(24)
#define CLIDR_FIELD_WIDTH	U(3)

/* CSSELR definitions */
#define CSSELR_LEVEL_SHIFT	U(1)

/* CTR definitions */
#define CTR_CWG_SHIFT		U(24)
#define CTR_CWG_MASK		U(0xf)
#define CTR_ERG_SHIFT		U(20)
#define CTR_ERG_MASK		U(0xf)
#define CTR_DMINLINE_SHIFT	U(16)
#define CTR_DMINLINE_WIDTH	U(4)
#define CTR_DMINLINE_MASK	(BIT(4) - 1)
#define CTR_L1IP_SHIFT		U(14)
#define CTR_L1IP_MASK		U(0x3)
#define CTR_IMINLINE_SHIFT	U(0)
#define CTR_IMINLINE_MASK	U(0xf)
#define CTR_WORD_SIZE		U(4)

#define ARM32_CPSR_MODE_MASK	U(0x1f)
#define ARM32_CPSR_MODE_USR	U(0x10)
#define ARM32_CPSR_MODE_FIQ	U(0x11)
#define ARM32_CPSR_MODE_IRQ	U(0x12)
#define ARM32_CPSR_MODE_SVC	U(0x13)
#define ARM32_CPSR_MODE_MON	U(0x16)
#define ARM32_CPSR_MODE_ABT	U(0x17)
#define ARM32_CPSR_MODE_UND	U(0x1b)
#define ARM32_CPSR_MODE_SYS	U(0x1f)

#define ARM32_CPSR_T		BIT(5)
#define ARM32_CPSR_F_SHIFT	U(6)
#define ARM32_CPSR_F		BIT(6)
#define ARM32_CPSR_I		BIT(7)
#define ARM32_CPSR_A		BIT(8)
#define ARM32_CPSR_E		BIT(9)
#define ARM32_CPSR_FIA		(ARM32_CPSR_F | ARM32_CPSR_I | ARM32_CPSR_A)
#define ARM32_CPSR_IT_MASK	(ARM32_CPSR_IT_MASK1 | ARM32_CPSR_IT_MASK2)
#define ARM32_CPSR_IT_MASK1	U(0x06000000)
#define ARM32_CPSR_IT_MASK2	U(0x0000fc00)

/* ARM Generic timer definitions */
#define CNTKCTL_PL0PCTEN	BIT(0) /* physical counter el0 access enable */
#define CNTKCTL_PL0VCTEN	BIT(1) /* virtual counter el0 access enable */

#ifdef ARM32
#include <arm32.h>
#endif

#ifdef ARM64
#include <arm64.h>
#endif
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (c) 2015, Linaro Limited
 */
#ifndef ARM64_H
#define ARM64_H

#include <compiler.h>
#include <sys/cdefs.h>
#include <stdint.h>
#include <util.h>

#define SCTLR_M		BIT64(0)
#define SCTLR_A		BIT64(1)
#define SCTLR_C		BIT64(2)
#define SCTLR_SA	BIT64(3)
#define SCTLR_I		BIT64(12)
#define SCTLR_ENDB	BIT64(13)
#define SCTLR_WXN	BIT64(19)
#define SCTLR_SPAN	BIT64(23)
#define SCTLR_ENDA	BIT64(27)
#define SCTLR_ENIB	BIT64(30)
#define SCTLR_ENIA	BIT64(31)
#define SCTLR_BT0	BIT64(35)
#define SCTLR_BT1	BIT64(36)
#define SCTLR_ITFSB	BIT64(37)

#define SCTLR_TCF_MASK	SHIFT_U64(0x3, 40)
#define SCTLR_TCF_NONE	SHIFT_U64(0x0, 40)
#define SCTLR_TCF_SYNC	SHIFT_U64(0x1, 40)
#define SCTLR_TCF_ASYNC	SHIFT_U64(0x2, 40)
#define SCTLR_TCF_ASYMM	SHIFT_U64(0x3, 40)

#define SCTLR_TCF0_MASK	SHIFT_U64(0x3, 38)
#define SCTLR_TCF0_NONE	SHIFT_U64(0x0, 38)
#define SCTLR_TCF0_SYNC	SHIFT_U64(0x1, 38)
#define SCTLR_TCF0_ASYNC SHIFT_U64(0x2, 38)
#define SCTLR_TCF0_ASYMM SHIFT_U64(0x3, 38)

#define SCTLR_ATA0	BIT64(42)
#define SCTLR_ATA	BIT64(43)

#define TTBR_ASID_MASK		U(0xff)
#define TTBR_ASID_SHIFT		U(48)

#define CLIDR_LOUIS_SHIFT	U(21)
#define CLIDR_LOC_SHIFT		U(24)
#define CLIDR_FIELD_WIDTH	U(3)

#define CSSELR_LEVEL_SHIFT	U(1)

#define DAIFBIT_FIQ			BIT32(0)
#define DAIFBIT_IRQ			BIT32(1)
#define DAIFBIT_ABT			BIT32(2)
#define DAIFBIT_DBG			BIT32(3)
#define DAIFBIT_ALL			(DAIFBIT_FIQ | DAIFBIT_IRQ | \
					 DAIFBIT_ABT | DAIFBIT_DBG)

#define DAIF_F_SHIFT		U(6)
#define DAIF_F			BIT32(6)
#define DAIF_I			BIT32(7)
#define DAIF_A			BIT32(8)
#define DAIF_D			BIT32(9)
#define DAIF_AIF		(DAIF_A | DAIF_I | DAIF_F)

#define SPSR_MODE_RW_SHIFT	U(4)
#define SPSR_MODE_RW_MASK	U(0x1)
#define SPSR_MODE_RW_64		U(0x0)
#define SPSR_MODE_RW_32		U(0x1)

#define SPSR_64_MODE_SP_SHIFT	U(0)
#define SPSR_64_MODE_SP_MASK	U(0x1)
#define SPSR_64_MODE_SP_EL0	U(0x0)
#define SPSR_64_MODE_SP_ELX	U(0x1)

#define SPSR_64_MODE_EL_SHIFT	U(2)
#define SPSR_64_MODE_EL_MASK	U(0x3)
#define SPSR_64_MODE_EL1	U(0x1)
#define SPSR_64_MODE_EL0	U(0x0)

#define SPSR_64_DAIF_SHIFT	U(6)
#define SPSR_64_DAIF_MASK	U(0xf)

#define SPSR_32_AIF_SHIFT	U(6)
#define SPSR_32_AIF_MASK	U(0x7)

#define SPSR_32_E_SHIFT		U(9)
#define SPSR_32_E_MASK		U(0x1)
#define SPSR_32_E_LITTLE	U(0x0)
#define SPSR_32_E_BIG		U(0x1)

#define SPSR_32_T_SHIFT		U(5)
#define SPSR_32_T_MASK		U(0x1)
#define SPSR_32_T_ARM		U(0x0)
#define SPSR_32_T_THUMB		U(0x1)

#define SPSR_32_MODE_SHIFT	U(0)
#define SPSR_32_MODE_MASK	U(0xf)
#define SPSR_32_MODE_USR	U(0x0)


#define SPSR_64(el, sp, daif)						\
	(SPSR_MODE_RW_64 << SPSR_MODE_RW_SHIFT |			\
	((el) & SPSR_64_MODE_EL_MASK) << SPSR_64_MODE_EL_SHIFT |	\
	((sp) & SPSR_64_MODE_SP_MASK) << SPSR_64_MODE_SP_SHIFT |	\
	((daif) & SPSR_64_DAIF_MASK) << SPSR_64_DAIF_SHIFT)

#define SPSR_32(mode, isa, aif)						\
	(SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT |			\
	SPSR_32_E_LITTLE << SPSR_32_E_SHIFT |				\
	((mode) & SPSR_32_MODE_MASK) << SPSR_32_MODE_SHIFT |		\
	((isa) & SPSR_32_T_MASK) << SPSR_32_T_SHIFT |			\
	((aif) & SPSR_32_AIF_MASK) << SPSR_32_AIF_SHIFT)


#define TCR_T0SZ_SHIFT		U(0)
#define TCR_EPD0		BIT64(7)
#define TCR_IRGN0_SHIFT		U(8)
#define TCR_ORGN0_SHIFT		U(10)
#define TCR_SH0_SHIFT		U(12)
#define TCR_T1SZ_SHIFT		U(16)
#define TCR_A1			BIT64(22)
#define TCR_EPD1		BIT64(23)
#define TCR_IRGN1_SHIFT		U(24)
#define TCR_ORGN1_SHIFT		U(26)
#define TCR_SH1_SHIFT		U(28)
#define TCR_EL1_IPS_SHIFT	U(32)
#define TCR_EL1_IPS_MASK	UINT64_C(0x7)
#define TCR_TG1_4KB		SHIFT_U64(2, 30)
#define TCR_RES1		BIT64(31)
#define TCR_TBI0		BIT64(37)
#define TCR_TBI1		BIT64(38)
#define TCR_TCMA0		BIT64(57)
#define TCR_TCMA1		BIT64(58)


/* Normal memory, Inner/Outer Non-cacheable */
#define TCR_XRGNX_NC		U(0x0)
/* Normal memory, Inner/Outer Write-Back Write-Allocate Cacheable */
#define TCR_XRGNX_WB		U(0x1)
/* Normal memory, Inner/Outer Write-Through Cacheable */
#define TCR_XRGNX_WT		U(0x2)
/* Normal memory, Inner/Outer Write-Back no Write-Allocate Cacheable */
#define TCR_XRGNX_WBWA		U(0x3)

/* Non-shareable */
#define TCR_SHX_NSH		U(0x0)
/* Outer Shareable */
#define TCR_SHX_OSH		U(0x2)
/* Inner Shareable */
#define TCR_SHX_ISH		U(0x3)

#define ESR_EC_SHIFT		U(26)
#define ESR_EC_MASK		U(0x3f)

#define ESR_EC_UNKNOWN		U(0x00)
#define ESR_EC_WFI		U(0x01)
#define ESR_EC_AARCH32_CP15_32	U(0x03)
#define ESR_EC_AARCH32_CP15_64	U(0x04)
#define ESR_EC_AARCH32_CP14_MR	U(0x05)
#define ESR_EC_AARCH32_CP14_LS	U(0x06)
#define ESR_EC_FP_ASIMD		U(0x07)
#define ESR_EC_AARCH32_CP10_ID	U(0x08)
#define ESR_EC_PAUTH		U(0x09)
#define ESR_EC_AARCH32_CP14_64	U(0x0c)
#define ESR_EC_BTI		U(0x0d)
#define ESR_EC_ILLEGAL		U(0x0e)
#define ESR_EC_AARCH32_SVC	U(0x11)
#define ESR_EC_AARCH64_SVC	U(0x15)
#define ESR_EC_AARCH64_SYS	U(0x18)
#define ESR_EC_ERET		U(0x1a)
#define ESR_EC_FPAC		U(0x1c)
#define ESR_EC_IABT_EL0		U(0x20)
#define ESR_EC_IABT_EL1		U(0x21)
#define ESR_EC_PC_ALIGN		U(0x22)
#define ESR_EC_DABT_EL0		U(0x24)
#define ESR_EC_DABT_EL1		U(0x25)
#define ESR_EC_SP_ALIGN		U(0x26)
#define ESR_EC_AARCH32_FP	U(0x28)
#define ESR_EC_AARCH64_FP	U(0x2c)
#define ESR_EC_SERROR		U(0x2f)
#define ESR_EC_BREAKPT_EL0	U(0x30)
#define ESR_EC_BREAKPT_EL1	U(0x31)
#define ESR_EC_SOFTSTP_EL0	U(0x32)
#define ESR_EC_SOFTSTP_EL1	U(0x33)
#define ESR_EC_WATCHPT_EL0	U(0x34)
#define ESR_EC_WATCHPT_EL1	U(0x35)
#define ESR_EC_AARCH32_BKPT	U(0x38)
#define ESR_EC_AARCH64_BRK	U(0x3c)

/* Combined defines for DFSC and IFSC */
#define ESR_FSC_MASK		U(0x3f)
#define ESR_FSC_SIZE_L0		U(0x00)
#define ESR_FSC_SIZE_L1		U(0x01)
#define ESR_FSC_SIZE_L2		U(0x02)
#define ESR_FSC_SIZE_L3		U(0x03)
#define ESR_FSC_TRANS_L0	U(0x04)
#define ESR_FSC_TRANS_L1	U(0x05)
#define ESR_FSC_TRANS_L2	U(0x06)
#define ESR_FSC_TRANS_L3	U(0x07)
#define ESR_FSC_ACCF_L1		U(0x09)
#define ESR_FSC_ACCF_L2		U(0x0a)
#define ESR_FSC_ACCF_L3		U(0x0b)
#define ESR_FSC_PERMF_L1	U(0x0d)
#define ESR_FSC_PERMF_L2	U(0x0e)
#define ESR_FSC_PERMF_L3	U(0x0f)
#define ESR_FSC_TAG_CHECK	U(0x11)
#define ESR_FSC_ALIGN		U(0x21)

/* WnR for DABT and RES0 for IABT */
#define ESR_ABT_WNR		BIT32(6)

#define CPACR_EL1_FPEN_SHIFT	U(20)
#define CPACR_EL1_FPEN_MASK	U(0x3)
#define CPACR_EL1_FPEN_NONE	U(0x0)
#define CPACR_EL1_FPEN_EL1	U(0x1)
#define CPACR_EL1_FPEN_EL0EL1	U(0x3)
#define CPACR_EL1_FPEN(x)	((x) >> CPACR_EL1_FPEN_SHIFT \
				      & CPACR_EL1_FPEN_MASK)


#define PAR_F			BIT32(0)
#define PAR_PA_SHIFT		U(12)
#define PAR_PA_MASK		(BIT64(36) - 1)

#define TLBI_MVA_SHIFT		U(12)
#define TLBI_ASID_SHIFT		U(48)
#define TLBI_ASID_MASK		U(0xff)

#define ID_AA64PFR1_EL1_BT_MASK	ULL(0xf)
#define FEAT_BTI_IMPLEMENTED	ULL(0x1)

#define ID_AA64PFR1_EL1_MTE_MASK	UL(0xf)
#define ID_AA64PFR1_EL1_MTE_SHIFT	U(8)
#define FEAT_MTE_NOT_IMPLEMENTED	U(0x0)
#define FEAT_MTE_IMPLEMENTED		U(0x1)
#define FEAT_MTE2_IMPLEMENTED		U(0x2)
#define FEAT_MTE3_IMPLEMENTED		U(0x3)

#define ID_AA64ISAR1_GPI_SHIFT		U(28)
#define ID_AA64ISAR1_GPI_MASK		U(0xf)
#define ID_AA64ISAR1_GPI_NI		U(0x0)
#define ID_AA64ISAR1_GPI_IMP_DEF	U(0x1)

#define ID_AA64ISAR1_GPA_SHIFT		U(24)
#define ID_AA64ISAR1_GPA_MASK		U(0xf)
#define ID_AA64ISAR1_GPA_NI		U(0x0)
#define ID_AA64ISAR1_GPA_ARCHITECTED	U(0x1)

#define ID_AA64ISAR1_API_SHIFT			U(8)
#define ID_AA64ISAR1_API_MASK			U(0xf)
#define ID_AA64ISAR1_API_NI			U(0x0)
#define ID_AA64ISAR1_API_IMP_DEF		U(0x1)
#define ID_AA64ISAR1_API_IMP_DEF_EPAC		U(0x2)
#define ID_AA64ISAR1_API_IMP_DEF_EPAC2		U(0x3)
#define ID_AA64ISAR1_API_IMP_DEF_EPAC2_FPAC	U(0x4)
#define ID_AA64ISAR1_API_IMP_DEF_EPAC2_FPAC_CMB	U(0x5)

#define ID_AA64ISAR1_APA_SHIFT			U(4)
#define ID_AA64ISAR1_APA_MASK			U(0xf)
#define ID_AA64ISAR1_APA_NI			U(0x0)
#define ID_AA64ISAR1_APA_ARCHITECTED		U(0x1)
#define ID_AA64ISAR1_APA_ARCH_EPAC		U(0x2)
#define ID_AA64ISAR1_APA_ARCH_EPAC2		U(0x3)
#define ID_AA64ISAR1_APA_ARCH_EPAC2_FPAC	U(0x4)
#define ID_AA64ISAR1_APA_ARCH_EPAC2_FPAC_CMB	U(0x5)

#define GCR_EL1_RRND				BIT64(16)

#ifndef __ASSEMBLER__
static inline __noprof void isb(void)
{
	asm volatile ("isb" : : : "memory");
}

static inline __noprof void dsb(void)
{
	asm volatile ("dsb sy" : : : "memory");
}

static inline __noprof void dsb_ish(void)
{
	asm volatile ("dsb ish" : : : "memory");
}

static inline __noprof void dsb_ishst(void)
{
	asm volatile ("dsb ishst" : : : "memory");
}

static inline __noprof void sev(void)
{
	asm volatile ("sev" : : : "memory");
}

static inline __noprof void wfe(void)
{
	asm volatile ("wfe" : : : "memory");
}

static inline __noprof void wfi(void)
{
	asm volatile ("wfi" : : : "memory");
}

static inline __noprof void write_at_s1e1r(uint64_t va)
{
	asm volatile ("at	S1E1R, %0" : : "r" (va));
}

static __always_inline __noprof uint64_t read_pc(void)
{
	uint64_t val;

	asm volatile ("adr %0, ." : "=r" (val));
	return val;
}

static __always_inline __noprof uint64_t read_fp(void)
{
	uint64_t val;

	asm volatile ("mov %0, x29" : "=r" (val));
	return val;
}

static inline __noprof uint64_t read_pmu_ccnt(void)
{
	uint64_t val;

	asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(val));
	return val;
}

static inline __noprof void tlbi_vaae1is(uint64_t mva)
{
	asm volatile ("tlbi	vaae1is, %0" : : "r" (mva));
}

static inline __noprof void tlbi_vale1is(uint64_t mva)
{
	asm volatile ("tlbi	vale1is, %0" : : "r" (mva));
}

/*
 * Templates for register read/write functions based on mrs/msr
 */

#define DEFINE_REG_READ_FUNC_(reg, type, asmreg)		\
static inline __noprof type read_##reg(void)			\
{								\
	uint64_t val64 = 0;					\
								\
	asm volatile("mrs %0, " #asmreg : "=r" (val64));	\
	return val64;						\
}

#define DEFINE_REG_WRITE_FUNC_(reg, type, asmreg)		\
static inline __noprof void write_##reg(type val)		\
{								\
	uint64_t val64 = val;					\
								\
	asm volatile("msr " #asmreg ", %0" : : "r" (val64));	\
}

#define DEFINE_U32_REG_READ_FUNC(reg) \
		DEFINE_REG_READ_FUNC_(reg, uint32_t, reg)

#define DEFINE_U32_REG_WRITE_FUNC(reg) \
		DEFINE_REG_WRITE_FUNC_(reg, uint32_t, reg)

#define DEFINE_U32_REG_READWRITE_FUNCS(reg)	\
		DEFINE_U32_REG_READ_FUNC(reg)	\
		DEFINE_U32_REG_WRITE_FUNC(reg)

#define DEFINE_U64_REG_READ_FUNC(reg) \
		DEFINE_REG_READ_FUNC_(reg, uint64_t, reg)

#define DEFINE_U64_REG_WRITE_FUNC(reg) \
		DEFINE_REG_WRITE_FUNC_(reg, uint64_t, reg)

#define DEFINE_U64_REG_READWRITE_FUNCS(reg)	\
		DEFINE_U64_REG_READ_FUNC(reg)	\
		DEFINE_U64_REG_WRITE_FUNC(reg)

/*
 * Define register access functions
 */

DEFINE_U32_REG_READWRITE_FUNCS(cpacr_el1)
DEFINE_U32_REG_READWRITE_FUNCS(daif)
DEFINE_U32_REG_READWRITE_FUNCS(fpcr)
DEFINE_U32_REG_READWRITE_FUNCS(fpsr)

DEFINE_U32_REG_READ_FUNC(ctr_el0)
#define read_ctr() read_ctr_el0()
DEFINE_U32_REG_READ_FUNC(contextidr_el1)
DEFINE_U64_REG_READ_FUNC(sctlr_el1)

/* ARM Generic timer functions */
DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0)
DEFINE_REG_READ_FUNC_(cntvct, uint64_t, cntvct_el0)
DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0)
DEFINE_REG_READ_FUNC_(cntkctl, uint32_t, cntkctl_el1)
DEFINE_REG_WRITE_FUNC_(cntkctl, uint32_t, cntkctl_el1)
DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
DEFINE_REG_WRITE_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
DEFINE_REG_READ_FUNC_(cntps_tval, uint32_t, cntps_tval_el1)
DEFINE_REG_WRITE_FUNC_(cntps_tval, uint32_t, cntps_tval_el1)

DEFINE_REG_READ_FUNC_(pmccntr, uint64_t, pmccntr_el0)

DEFINE_U64_REG_READWRITE_FUNCS(ttbr0_el1)
DEFINE_U64_REG_READWRITE_FUNCS(ttbr1_el1)
DEFINE_U64_REG_READWRITE_FUNCS(tcr_el1)

DEFINE_U64_REG_READ_FUNC(esr_el1)
DEFINE_U64_REG_READ_FUNC(far_el1)
DEFINE_U64_REG_READ_FUNC(mpidr_el1)
/* Alias for reading this register to avoid ifdefs in code */
#define read_mpidr() read_mpidr_el1()
DEFINE_U64_REG_READ_FUNC(midr_el1)
/* Alias for reading this register to avoid ifdefs in code */
#define read_midr() read_midr_el1()
DEFINE_U64_REG_READ_FUNC(par_el1)

DEFINE_U64_REG_WRITE_FUNC(mair_el1)

DEFINE_U64_REG_READ_FUNC(id_aa64pfr1_el1)
DEFINE_U64_REG_READ_FUNC(id_aa64isar1_el1)
DEFINE_REG_READ_FUNC_(apiakeylo, uint64_t, S3_0_c2_c1_0)
DEFINE_REG_READ_FUNC_(apiakeyhi, uint64_t, S3_0_c2_c1_1)

DEFINE_REG_WRITE_FUNC_(apibkeylo, uint64_t, S3_0_c2_c1_2)
DEFINE_REG_WRITE_FUNC_(apibkeyhi, uint64_t, S3_0_c2_c1_3)

DEFINE_REG_READ_FUNC_(apdakeylo, uint64_t, S3_0_c2_c2_0)
DEFINE_REG_READ_FUNC_(apdakeyhi, uint64_t, S3_0_c2_c2_1)

DEFINE_REG_WRITE_FUNC_(apdbkeylo, uint64_t, S3_0_c2_c2_2)
DEFINE_REG_WRITE_FUNC_(apdbkeyhi, uint64_t, S3_0_c2_c2_3)

DEFINE_REG_WRITE_FUNC_(apgakeylo, uint64_t, S3_0_c2_c3_0)
DEFINE_REG_WRITE_FUNC_(apgakeyhi, uint64_t, S3_0_c2_c3_1)

/* Register read/write functions for GICC registers by using system interface */
DEFINE_REG_READ_FUNC_(icc_ctlr, uint32_t, S3_0_C12_C12_4)
DEFINE_REG_WRITE_FUNC_(icc_ctlr, uint32_t, S3_0_C12_C12_4)
DEFINE_REG_WRITE_FUNC_(icc_pmr, uint32_t, S3_0_C4_C6_0)
DEFINE_REG_READ_FUNC_(icc_iar0, uint32_t, S3_0_c12_c8_0)
DEFINE_REG_READ_FUNC_(icc_iar1, uint32_t, S3_0_c12_c12_0)
DEFINE_REG_WRITE_FUNC_(icc_eoir0, uint32_t, S3_0_c12_c8_1)
DEFINE_REG_WRITE_FUNC_(icc_eoir1, uint32_t, S3_0_c12_c12_1)
DEFINE_REG_WRITE_FUNC_(icc_igrpen0, uint32_t, S3_0_C12_C12_6)
DEFINE_REG_WRITE_FUNC_(icc_igrpen1, uint32_t, S3_0_C12_C12_7)
#endif /*__ASSEMBLER__*/

#endif /*ARM64_H*/


posted @ 2025-05-06 16:51  颜小雀  阅读(210)  评论(0)    收藏  举报