更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_hw_cpu.h
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/**
33 * @defgroup los_hw Hardware
34 * @ingroup kernel
35 */
36
37#ifndef _LOS_HW_CPU_H
38#define _LOS_HW_CPU_H
39
40#include "los_typedef.h"
41#include "los_toolchain.h"
42#include "los_hw_arch.h"
43
44#ifdef __cplusplus
45#if __cplusplus
46extern "C" {
47#endif /* __cplusplus */
48#endif /* __cplusplus */
49
50/*!
51 * @brief 内存屏障(英语:Memory barrier),也称内存栅栏,内存栅障,屏障指令等,是一类同步屏障指令,
52 \n 它使得 CPU 或编译器在对内存进行操作的时候, 严格按照一定的顺序来执行, 也就是说在memory barrier 之前的指令
53 \n 和memory barrier之后的指令不会由于系统优化等原因而导致乱序。
54 \n 大多数现代计算机为了提高性能而采取乱序执行,这使得内存屏障成为必须。
55
56 \n 语义上,内存屏障之前的所有写操作都要写入内存;内存屏障之后的读操作都可以获得同步屏障之前的写操作的结果。
57 \n 因此,对于敏感的程序块,写操作之后、读操作之前可以插入内存屏障。
58 *
59 * @param index
60 * @return
61 *
62 * @see
63 */
64
65
66// https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/memory-access-ordering---an-introduction
67/* ARM System Registers */
68#define DSB __asm__ volatile("dsb" ::: "memory") ///< Data Synchronization Barrier(DSB) 数据同步隔离。DSB 比 DMB 管得更宽, DSB 屏障之后的所有得指令不可越过屏障乱序执行
69#define DMB __asm__ volatile("dmb" ::: "memory") ///< Data Memory Barrier(DMB) 数据存储器隔离。保证该指令前的所有内存访问结束,而该指令之后引起的内存访问只能在该指令执行结束后开始,其它数据处理指令等可以越过 DMB 屏障乱序执行
70#define ISB __asm__ volatile("isb" ::: "memory") ///< Instruction Synchronization Barrier(ISB) 指令同步隔离。ISB 比 DSB 管的更宽, ISB 屏障之前的指令保证执行完,屏障之后的指令直接flush 掉再重新从 Memroy 中取指
71#define WFI __asm__ volatile("wfi" ::: "memory")
72#define BARRIER __asm__ volatile("":::"memory")
73#define WFE __asm__ volatile("wfe" ::: "memory")
74#define SEV __asm__ volatile("sev" ::: "memory")
75
76#define ARM_SYSREG_READ(REG) \
77({ \
78 UINT32 _val; \
79 __asm__ volatile("mrc " REG : "=r" (_val)); \
80 _val; \
81})
82
83#define ARM_SYSREG_WRITE(REG, val) \
84({ \
85 __asm__ volatile("mcr " REG :: "r" (val)); \
86 ISB; \
87})
88
89#define ARM_SYSREG64_READ(REG) \
90({ \
91 UINT64 _val; \
92 __asm__ volatile("mrrc " REG : "=r" (_val)); \
93 _val; \
94})
95
96#define ARM_SYSREG64_WRITE(REG, val) \
97({ \
98 __asm__ volatile("mcrr " REG :: "r" (val)); \
99 ISB; \
100})
101
102#define CP14_REG(CRn, Op1, CRm, Op2) "p14, "#Op1", %0, "#CRn","#CRm","#Op2
103#define CP15_REG(CRn, Op1, CRm, Op2) "p15, "#Op1", %0, "#CRn","#CRm","#Op2
104#define CP15_REG64(CRn, Op1) "p15, "#Op1", %0, %H0,"#CRn
105//CP15 协处理器各寄存器信息
106/*!
107 * Identification registers (c0) | c0 - 身份寄存器 详见 鸿蒙内核源码分析(协处理器篇)
108 */
109#define MIDR CP15_REG(c0, 0, c0, 0) /*! Main ID Register | 主ID寄存器 */
110#define MPIDR CP15_REG(c0, 0, c0, 5) /*! Multiprocessor Affinity Register | 多处理器关联寄存器给每个CPU制定一个逻辑地址*/
111#define CCSIDR CP15_REG(c0, 1, c0, 0) /*! Cache Size ID Registers | 缓存大小ID寄存器*/
112#define CLIDR CP15_REG(c0, 1, c0, 1) /*! Cache Level ID Register | 缓存登记ID寄存器*/
113#define VPIDR CP15_REG(c0, 4, c0, 0) /*! Virtualization Processor ID Register | 虚拟化处理器ID寄存器*/
114#define VMPIDR CP15_REG(c0, 4, c0, 5) /*! Virtualization Multiprocessor ID Register | 虚拟化多处理器ID寄存器*/
115
116/*!
117 * System control registers (c1) | c1 - 系统控制寄存器 各种控制位(可读写)
118 */
119#define SCTLR CP15_REG(c1, 0, c0, 0) /*! System Control Register | 系统控制寄存器*/
120#define ACTLR CP15_REG(c1, 0, c0, 1) /*! Auxiliary Control Register | 辅助控制寄存器*/
121#define CPACR CP15_REG(c1, 0, c0, 2) /*! Coprocessor Access Control Register | 协处理器访问控制寄存器*/
122
123/*!
124 * Memory protection and control registers (c2 & c3) | c2 - 传说中的TTB寄存器,主要是给MMU使用 c3 - 域访问控制位
125 */
126#define TTBR0 CP15_REG(c2, 0, c0, 0) /*! Translation Table Base Register 0 | 转换表基地址寄存器0*/
127#define TTBR1 CP15_REG(c2, 0, c0, 1) /*! Translation Table Base Register 1 | 转换表基地址寄存器1*/
128#define TTBCR CP15_REG(c2, 0, c0, 2) /*! Translation Table Base Control Register | 转换表基地址控制寄存器*/
129#define DACR CP15_REG(c3, 0, c0, 0) /*! Domain Access Control Register | 域访问控制寄存器*/
130
131/*!
132 * Memory system fault registers (c5 & c6) | c5 - 内存失效状态 c6 - 内存失效地址
133 */
134#define DFSR CP15_REG(c5, 0, c0, 0) /*! Data Fault Status Register | 数据故障状态寄存器 */
135#define IFSR CP15_REG(c5, 0, c0, 1) /*! Instruction Fault Status Register | 指令故障状态寄存器*/
136#define DFAR CP15_REG(c6, 0, c0, 0) /*! Data Fault Address Register | 数据故障地址寄存器*/
137#define IFAR CP15_REG(c6, 0, c0, 2) /*! Instruction Fault Address Register | 指令错误地址寄存器*/
138
139/*!
140 * Process, context and thread ID registers (c13) | c13 - 进程标识符
141 */
142#define FCSEIDR CP15_REG(c13, 0, c0, 0) /*! FCSE Process ID Register | FCSE(Fast Context Switch Extension,快速上下文切换)进程ID寄存器 位于CPU和MMU之间*/
143#define CONTEXTIDR CP15_REG(c13, 0, c0, 1) /*! Context ID Register | 上下文ID寄存器*/
144#define TPIDRURW CP15_REG(c13, 0, c0, 2) /*! User Read/Write Thread ID Register | 用户读/写线程ID寄存器*/
145#define TPIDRURO CP15_REG(c13, 0, c0, 3) /*! User Read-Only Thread ID Register | 用户只读写线程ID寄存器*/
146#define TPIDRPRW CP15_REG(c13, 0, c0, 4) /*! PL1 only Thread ID Register | 仅PL1线程ID寄存器*/
147
148#define MPIDR_CPUID_MASK (0xffU)
149/// 获取当前task的地址
150STATIC INLINE VOID *ArchCurrTaskGet(VOID)
151{
152 return (VOID *)(UINTPTR)ARM_SYSREG_READ(TPIDRPRW);//读c13寄存器
153}
154/// 向CP15 - > C13 保存当前任务的地址
155STATIC INLINE VOID ArchCurrTaskSet(VOID *val)
156{
157 ARM_SYSREG_WRITE(TPIDRPRW, (UINT32)(UINTPTR)val);
158}
159/// 向协处理器写入用户态任务ID TPIDRURO 仅用于用户态
160STATIC INLINE VOID ArchCurrUserTaskSet(UINTPTR val)
161{
162 ARM_SYSREG_WRITE(TPIDRURO, (UINT32)val);
163}
164/*!
165* https://www.keil.com/pack/doc/cmsis/Core_A/html/group__CMSIS__MPIDR.html
166* 在多处理器系统中,MPIDR为调度目的提供额外的处理器标识机制,并指示实现是否包括多处理器扩展。
167*/
168STATIC INLINE UINT32 ArchCurrCpuid(VOID)
169{
170#ifdef LOSCFG_KERNEL_SMP
171 return ARM_SYSREG_READ(MPIDR) & MPIDR_CPUID_MASK;
172#else//ARM架构通过MPIDR(Multiprocessor Affinity Register)寄存器给每个CPU指定一个逻辑地址。
173 return 0;
174#endif
175}
176/// 获取CPU硬件ID,每个CPU都有自己的唯一标识
177STATIC INLINE UINT64 OsHwIDGet(VOID)
178{
179 return ARM_SYSREG_READ(MPIDR);
180}
181///获取CPU型号,包含CPU各种信息,例如:[15:4]表示 arm 7或arm 9
182STATIC INLINE UINT32 OsMainIDGet(VOID)
183{
184 return ARM_SYSREG_READ(MIDR);
185}
186
187/* CPU interrupt mask handle implementation | CPU中断掩码句柄实现*/
188#if LOSCFG_ARM_ARCH >= 6
189///禁止中断
190STATIC INLINE UINT32 ArchIntLock(VOID)
191{
192 UINT32 intSave;
193 __asm__ __volatile__(
194 "mrs %0, cpsr \n"
195 "cpsid if "
196 : "=r"(intSave)
197 :
198 : "memory");
199 return intSave;
200}
201//恢复中断
202STATIC INLINE UINT32 ArchIntUnlock(VOID)
203{
204 UINT32 intSave;
205 __asm__ __volatile__(
206 "mrs %0, cpsr \n"
207 "cpsie if "
208 : "=r"(intSave)
209 :
210 : "memory");
211 return intSave;
212}
213
214STATIC INLINE VOID ArchIrqDisable(VOID)
215{
216 __asm__ __volatile__(
217 "cpsid i "
218 :
219 :
220 : "memory", "cc");
221}
222
223STATIC INLINE VOID ArchIrqEnable(VOID)
224{
225 __asm__ __volatile__(
226 "cpsie i "
227 :
228 :
229 : "memory", "cc");
230}
231
232#else
233
234STATIC INLINE UINT32 ArchIntLock(VOID)
235{
236 UINT32 intSave, temp;
237 __asm__ __volatile__(
238 "mrs %0, cpsr \n"
239 "orr %1, %0, #0xc0 \n"
240 "msr cpsr_c, %1 "
241 :"=r"(intSave), "=r"(temp)
242 : :"memory");
243 return intSave;
244}
245/// 打开当前处理器所有中断响应
246STATIC INLINE UINT32 ArchIntUnlock(VOID)
247{
248 UINT32 intSave;
249 __asm__ __volatile__(
250 "mrs %0, cpsr \n"
251 "bic %0, %0, #0xc0 \n"
252 "msr cpsr_c, %0 "
253 : "=r"(intSave)
254 : : "memory");
255 return intSave;
256}
257
258#endif
259/// 恢复到使用LOS_IntLock关闭所有中断之前的状态
260STATIC INLINE VOID ArchIntRestore(UINT32 intSave)
261{
262 __asm__ __volatile__(
263 "msr cpsr_c, %0 "
264 :
265 : "r"(intSave)
266 : "memory");
267}
268
269#define PSR_I_BIT 0x00000080U
270/// 关闭当前处理器所有中断响应
271STATIC INLINE UINT32 OsIntLocked(VOID)
272{
273 UINT32 intSave;
274
275 asm volatile(
276 "mrs %0, cpsr "
277 : "=r" (intSave)
278 :
279 : "memory", "cc");
280
281 return intSave & PSR_I_BIT;
282}
283
284STATIC INLINE UINT32 ArchSPGet(VOID)
285{
286 UINT32 val;
287 __asm__ __volatile__("mov %0, sp" : "=r"(val));
288 return val;
289}
290
291#ifdef __cplusplus
292#if __cplusplus
293}
294#endif /* __cplusplus */
295#endif /* __cplusplus */
296
297#endif /* _LOS_HW_CPU_H */
STATIC INLINE VOID ArchIrqDisable(VOID)
Definition: los_hw_cpu.h:214
STATIC INLINE UINT32 ArchSPGet(VOID)
Definition: los_hw_cpu.h:284
STATIC INLINE VOID ArchCurrUserTaskSet(UINTPTR val)
向协处理器写入用户态任务ID TPIDRURO 仅用于用户态
Definition: los_hw_cpu.h:160
STATIC INLINE UINT32 OsMainIDGet(VOID)
获取CPU型号,包含CPU各种信息,例如:[15:4]表示 arm 7或arm 9
Definition: los_hw_cpu.h:182
STATIC INLINE UINT32 OsIntLocked(VOID)
关闭当前处理器所有中断响应
Definition: los_hw_cpu.h:271
STATIC INLINE UINT32 ArchCurrCpuid(VOID)
Definition: los_hw_cpu.h:168
STATIC INLINE UINT32 ArchIntUnlock(VOID)
打开当前处理器所有中断响应
Definition: los_hw_cpu.h:202
STATIC INLINE VOID * ArchCurrTaskGet(VOID)
获取当前task的地址
Definition: los_hw_cpu.h:150
STATIC INLINE VOID ArchIntRestore(UINT32 intSave)
恢复到使用LOS_IntLock关闭所有中断之前的状态
Definition: los_hw_cpu.h:260
STATIC INLINE VOID ArchIrqEnable(VOID)
Definition: los_hw_cpu.h:223
STATIC INLINE UINT32 ArchIntLock(VOID)
禁止中断
Definition: los_hw_cpu.h:190
STATIC INLINE VOID ArchCurrTaskSet(VOID *val)
向CP15 - > C13 保存当前任务的地址
Definition: los_hw_cpu.h:155
STATIC INLINE UINT64 OsHwIDGet(VOID)
获取CPU硬件ID,每个CPU都有自己的唯一标识
Definition: los_hw_cpu.h:177
long unsigned int UINT64
Definition: los_typedef.h:66
unsigned long UINTPTR
Definition: los_typedef.h:68
unsigned int UINT32
Definition: los_typedef.h:57