1/*
2 * Copyright 2018, Jaroslaw Pelczar <jarek@jpelczar.com>
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _KERNEL_ARCH_ARM64_ARCH_CPU_H_
6#define _KERNEL_ARCH_ARM64_ARCH_CPU_H_
7
8
9#define CPU_MAX_CACHE_LEVEL 	8
10#define CACHE_LINE_SIZE 		64
11
12#define set_ac()
13#define clear_ac()
14
15#include <kernel/arch/arm64/arm_registers.h>
16
17#ifndef _ASSEMBLER
18
19#include <arch/arm64/arch_thread_types.h>
20#include <kernel.h>
21
22#define arm64_sev()  		__asm__ __volatile__("sev" : : : "memory")
23#define arm64_wfe()  		__asm__ __volatile__("wfe" : : : "memory")
24#define arm64_dsb()  		__asm__ __volatile__("dsb" : : : "memory")
25#define arm64_dmb()  		__asm__ __volatile__("dmb" : : : "memory")
26#define arm64_isb()  		__asm__ __volatile__("isb" : : : "memory")
27#define arm64_nop()  		__asm__ __volatile__("nop" : : : "memory")
28#define arm64_wfi()  		__asm__ __volatile__("wfi" : : : "memory")
29#define arm64_yield() 	__asm__ __volatile__("yield" : : : "memory")
30
31/* Extract CPU affinity levels 0-3 */
32#define	CPU_AFF0(mpidr)	(u_int)(((mpidr) >> 0) & 0xff)
33#define	CPU_AFF1(mpidr)	(u_int)(((mpidr) >> 8) & 0xff)
34#define	CPU_AFF2(mpidr)	(u_int)(((mpidr) >> 16) & 0xff)
35#define	CPU_AFF3(mpidr)	(u_int)(((mpidr) >> 32) & 0xff)
36#define	CPU_AFF0_MASK	0xffUL
37#define	CPU_AFF1_MASK	0xff00UL
38#define	CPU_AFF2_MASK	0xff0000UL
39#define	CPU_AFF3_MASK	0xff00000000UL
40#define	CPU_AFF_MASK	(CPU_AFF0_MASK | CPU_AFF1_MASK | \
41    CPU_AFF2_MASK| CPU_AFF3_MASK)	/* Mask affinity fields in MPIDR_EL1 */
42
43
44#define	CPU_IMPL_ARM		0x41
45#define	CPU_IMPL_BROADCOM	0x42
46#define	CPU_IMPL_CAVIUM		0x43
47#define	CPU_IMPL_DEC		0x44
48#define	CPU_IMPL_INFINEON	0x49
49#define	CPU_IMPL_FREESCALE	0x4D
50#define	CPU_IMPL_NVIDIA		0x4E
51#define	CPU_IMPL_APM		0x50
52#define	CPU_IMPL_QUALCOMM	0x51
53#define	CPU_IMPL_MARVELL	0x56
54#define	CPU_IMPL_INTEL		0x69
55
56#define	CPU_PART_THUNDER	0x0A1
57#define	CPU_PART_FOUNDATION	0xD00
58#define	CPU_PART_CORTEX_A35	0xD04
59#define	CPU_PART_CORTEX_A53	0xD03
60#define	CPU_PART_CORTEX_A55	0xD05
61#define	CPU_PART_CORTEX_A57	0xD07
62#define	CPU_PART_CORTEX_A72	0xD08
63#define	CPU_PART_CORTEX_A73	0xD09
64#define	CPU_PART_CORTEX_A75	0xD0A
65
66#define	CPU_REV_THUNDER_1_0	0x00
67#define	CPU_REV_THUNDER_1_1	0x01
68
69#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
70#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
71#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
72#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
73
74#define	CPU_IMPL_TO_MIDR(val)	(((val) & 0xff) << 24)
75#define	CPU_PART_TO_MIDR(val)	(((val) & 0xfff) << 4)
76#define	CPU_VAR_TO_MIDR(val)	(((val) & 0xf) << 20)
77#define	CPU_REV_TO_MIDR(val)	(((val) & 0xf) << 0)
78
79#define	CPU_IMPL_MASK	(0xff << 24)
80#define	CPU_PART_MASK	(0xfff << 4)
81#define	CPU_VAR_MASK	(0xf << 20)
82#define	CPU_REV_MASK	(0xf << 0)
83
84#define	CPU_ID_RAW(impl, part, var, rev)		\
85    (CPU_IMPL_TO_MIDR((impl)) |				\
86    CPU_PART_TO_MIDR((part)) | CPU_VAR_TO_MIDR((var)) |	\
87    CPU_REV_TO_MIDR((rev)))
88
89#define	CPU_MATCH(mask, impl, part, var, rev)		\
90    (((mask) & PCPU_GET(midr)) ==			\
91    ((mask) & CPU_ID_RAW((impl), (part), (var), (rev))))
92
93#define	CPU_MATCH_RAW(mask, devid)			\
94    (((mask) & PCPU_GET(midr)) == ((mask) & (devid)))
95
96static inline uint64 arm64_get_cyclecount(void)
97{
98	return READ_SPECIALREG(cntvct_el0);
99}
100
101#define	ADDRESS_TRANSLATE_FUNC(stage)					\
102static inline uint64									\
103arm64_address_translate_ ##stage (uint64 addr)		\
104{														\
105	uint64 ret;											\
106														\
107	__asm __volatile(									\
108	    "at " __ARMREG_STRING(stage) ", %1 \n"					\
109	    "mrs %0, par_el1" : "=r"(ret) : "r"(addr));		\
110														\
111	return (ret);										\
112}
113
114
115ADDRESS_TRANSLATE_FUNC(s1e0r)
116ADDRESS_TRANSLATE_FUNC(s1e0w)
117ADDRESS_TRANSLATE_FUNC(s1e1r)
118ADDRESS_TRANSLATE_FUNC(s1e1w)
119
120
121struct aarch64_fpu_state
122{
123	uint64 regs[32 * 2];
124	uint64 fpsr;
125	uint64 fpcr;
126};
127
128
129/* raw exception frames */
130struct iframe {
131	// return info
132	uint64 elr;
133	uint64 spsr;
134	uint64 x[20];
135	uint64 lr;
136	uint64 sp;
137	uint64 fp;
138
139	// exception info
140	uint64 esr;
141	uint64 far;
142
143	// fpu
144	struct aarch64_fpu_state fpu;
145};
146
147
148#ifdef __cplusplus
149namespace BKernel {
150	struct Thread;
151}  // namespace BKernel
152
153
154typedef struct arch_cpu_info {
155	uint32						mpidr;
156	BKernel::Thread*			last_vfp_user;
157} arch_cpu_info;
158#endif
159
160
161#ifdef __cplusplus
162extern "C" {
163#endif
164
165
166static inline void arch_cpu_pause(void)
167{
168	arm64_yield();
169}
170
171
172static inline void arch_cpu_idle(void)
173{
174	arm64_wfi();
175}
176
177
178extern addr_t arm64_get_fp(void);
179
180
181#ifdef __cplusplus
182}
183#endif
184
185#endif
186
187
188#endif /* _KERNEL_ARCH_ARM64_ARCH_CPU_H_ */
189