xref: /haiku/headers/private/kernel/arch/arm64/arch_cpu.h (revision c2f3786ab0d58b5eb08b3d3fe28f7eb85c40027f)
13a72e3ebSJaroslaw Pelczar /*
23a72e3ebSJaroslaw Pelczar  * Copyright 2018, Jaroslaw Pelczar <jarek@jpelczar.com>
33a72e3ebSJaroslaw Pelczar  * Distributed under the terms of the MIT License.
43a72e3ebSJaroslaw Pelczar  */
53a72e3ebSJaroslaw Pelczar #ifndef _KERNEL_ARCH_ARM64_ARCH_CPU_H_
63a72e3ebSJaroslaw Pelczar #define _KERNEL_ARCH_ARM64_ARCH_CPU_H_
73a72e3ebSJaroslaw Pelczar 
83a72e3ebSJaroslaw Pelczar 
93a72e3ebSJaroslaw Pelczar #define CPU_MAX_CACHE_LEVEL 	8
103a72e3ebSJaroslaw Pelczar #define CACHE_LINE_SIZE 		64
113a72e3ebSJaroslaw Pelczar 
1281af0919SOwen Anderson // TODO: These will require a real implementation when PAN is enabled
136f88de11SAugustin Cavalier #define arch_cpu_enable_user_access()
146f88de11SAugustin Cavalier #define arch_cpu_disable_user_access()
153a72e3ebSJaroslaw Pelczar 
161761cb8eSJaroslaw Pelczar #include <kernel/arch/arm64/arm_registers.h>
173a72e3ebSJaroslaw Pelczar 
183a72e3ebSJaroslaw Pelczar #ifndef _ASSEMBLER
193a72e3ebSJaroslaw Pelczar 
203a72e3ebSJaroslaw Pelczar #include <arch/arm64/arch_thread_types.h>
213a72e3ebSJaroslaw Pelczar #include <kernel.h>
223a72e3ebSJaroslaw Pelczar 
233a72e3ebSJaroslaw Pelczar #define arm64_sev()  		__asm__ __volatile__("sev" : : : "memory")
243a72e3ebSJaroslaw Pelczar #define arm64_wfe()  		__asm__ __volatile__("wfe" : : : "memory")
253a72e3ebSJaroslaw Pelczar #define arm64_dsb()  		__asm__ __volatile__("dsb" : : : "memory")
263a72e3ebSJaroslaw Pelczar #define arm64_dmb()  		__asm__ __volatile__("dmb" : : : "memory")
273a72e3ebSJaroslaw Pelczar #define arm64_isb()  		__asm__ __volatile__("isb" : : : "memory")
283a72e3ebSJaroslaw Pelczar #define arm64_nop()  		__asm__ __volatile__("nop" : : : "memory")
296034ee94Smilek7 #define arm64_wfi()  		__asm__ __volatile__("wfi" : : : "memory")
303a72e3ebSJaroslaw Pelczar #define arm64_yield() 	__asm__ __volatile__("yield" : : : "memory")
313a72e3ebSJaroslaw Pelczar 
323a72e3ebSJaroslaw Pelczar /* Extract CPU affinity levels 0-3 */
333a72e3ebSJaroslaw Pelczar #define	CPU_AFF0(mpidr)	(u_int)(((mpidr) >> 0) & 0xff)
343a72e3ebSJaroslaw Pelczar #define	CPU_AFF1(mpidr)	(u_int)(((mpidr) >> 8) & 0xff)
353a72e3ebSJaroslaw Pelczar #define	CPU_AFF2(mpidr)	(u_int)(((mpidr) >> 16) & 0xff)
363a72e3ebSJaroslaw Pelczar #define	CPU_AFF3(mpidr)	(u_int)(((mpidr) >> 32) & 0xff)
373a72e3ebSJaroslaw Pelczar #define	CPU_AFF0_MASK	0xffUL
383a72e3ebSJaroslaw Pelczar #define	CPU_AFF1_MASK	0xff00UL
393a72e3ebSJaroslaw Pelczar #define	CPU_AFF2_MASK	0xff0000UL
403a72e3ebSJaroslaw Pelczar #define	CPU_AFF3_MASK	0xff00000000UL
413a72e3ebSJaroslaw Pelczar #define	CPU_AFF_MASK	(CPU_AFF0_MASK | CPU_AFF1_MASK | \
423a72e3ebSJaroslaw Pelczar     CPU_AFF2_MASK| CPU_AFF3_MASK)	/* Mask affinity fields in MPIDR_EL1 */
433a72e3ebSJaroslaw Pelczar 
443a72e3ebSJaroslaw Pelczar 
453a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_ARM		0x41
463a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_BROADCOM	0x42
473a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_CAVIUM		0x43
483a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_DEC		0x44
493a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_INFINEON	0x49
503a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_FREESCALE	0x4D
513a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_NVIDIA		0x4E
523a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_APM		0x50
533a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_QUALCOMM	0x51
543a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_MARVELL	0x56
553a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_INTEL		0x69
563a72e3ebSJaroslaw Pelczar 
573a72e3ebSJaroslaw Pelczar #define	CPU_PART_THUNDER	0x0A1
583a72e3ebSJaroslaw Pelczar #define	CPU_PART_FOUNDATION	0xD00
593a72e3ebSJaroslaw Pelczar #define	CPU_PART_CORTEX_A35	0xD04
603a72e3ebSJaroslaw Pelczar #define	CPU_PART_CORTEX_A53	0xD03
613a72e3ebSJaroslaw Pelczar #define	CPU_PART_CORTEX_A55	0xD05
623a72e3ebSJaroslaw Pelczar #define	CPU_PART_CORTEX_A57	0xD07
633a72e3ebSJaroslaw Pelczar #define	CPU_PART_CORTEX_A72	0xD08
643a72e3ebSJaroslaw Pelczar #define	CPU_PART_CORTEX_A73	0xD09
653a72e3ebSJaroslaw Pelczar #define	CPU_PART_CORTEX_A75	0xD0A
663a72e3ebSJaroslaw Pelczar 
673a72e3ebSJaroslaw Pelczar #define	CPU_REV_THUNDER_1_0	0x00
683a72e3ebSJaroslaw Pelczar #define	CPU_REV_THUNDER_1_1	0x01
693a72e3ebSJaroslaw Pelczar 
703a72e3ebSJaroslaw Pelczar #define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
713a72e3ebSJaroslaw Pelczar #define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
723a72e3ebSJaroslaw Pelczar #define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
733a72e3ebSJaroslaw Pelczar #define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
743a72e3ebSJaroslaw Pelczar 
753a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_TO_MIDR(val)	(((val) & 0xff) << 24)
763a72e3ebSJaroslaw Pelczar #define	CPU_PART_TO_MIDR(val)	(((val) & 0xfff) << 4)
773a72e3ebSJaroslaw Pelczar #define	CPU_VAR_TO_MIDR(val)	(((val) & 0xf) << 20)
783a72e3ebSJaroslaw Pelczar #define	CPU_REV_TO_MIDR(val)	(((val) & 0xf) << 0)
793a72e3ebSJaroslaw Pelczar 
803a72e3ebSJaroslaw Pelczar #define	CPU_IMPL_MASK	(0xff << 24)
813a72e3ebSJaroslaw Pelczar #define	CPU_PART_MASK	(0xfff << 4)
823a72e3ebSJaroslaw Pelczar #define	CPU_VAR_MASK	(0xf << 20)
833a72e3ebSJaroslaw Pelczar #define	CPU_REV_MASK	(0xf << 0)
843a72e3ebSJaroslaw Pelczar 
853a72e3ebSJaroslaw Pelczar #define	CPU_ID_RAW(impl, part, var, rev)		\
863a72e3ebSJaroslaw Pelczar     (CPU_IMPL_TO_MIDR((impl)) |				\
873a72e3ebSJaroslaw Pelczar     CPU_PART_TO_MIDR((part)) | CPU_VAR_TO_MIDR((var)) |	\
883a72e3ebSJaroslaw Pelczar     CPU_REV_TO_MIDR((rev)))
893a72e3ebSJaroslaw Pelczar 
903a72e3ebSJaroslaw Pelczar #define	CPU_MATCH(mask, impl, part, var, rev)		\
913a72e3ebSJaroslaw Pelczar     (((mask) & PCPU_GET(midr)) ==			\
923a72e3ebSJaroslaw Pelczar     ((mask) & CPU_ID_RAW((impl), (part), (var), (rev))))
933a72e3ebSJaroslaw Pelczar 
943a72e3ebSJaroslaw Pelczar #define	CPU_MATCH_RAW(mask, devid)			\
953a72e3ebSJaroslaw Pelczar     (((mask) & PCPU_GET(midr)) == ((mask) & (devid)))
963a72e3ebSJaroslaw Pelczar 
arm64_get_cyclecount(void)973a72e3ebSJaroslaw Pelczar static inline uint64 arm64_get_cyclecount(void)
983a72e3ebSJaroslaw Pelczar {
993a72e3ebSJaroslaw Pelczar 	return READ_SPECIALREG(cntvct_el0);
1003a72e3ebSJaroslaw Pelczar }
1013a72e3ebSJaroslaw Pelczar 
1023a72e3ebSJaroslaw Pelczar #define	ADDRESS_TRANSLATE_FUNC(stage)					\
1033a72e3ebSJaroslaw Pelczar static inline uint64									\
1043a72e3ebSJaroslaw Pelczar arm64_address_translate_ ##stage (uint64 addr)		\
1053a72e3ebSJaroslaw Pelczar {														\
1063a72e3ebSJaroslaw Pelczar 	uint64 ret;											\
1073a72e3ebSJaroslaw Pelczar 														\
1083a72e3ebSJaroslaw Pelczar 	__asm __volatile(									\
1091761cb8eSJaroslaw Pelczar 	    "at " __ARMREG_STRING(stage) ", %1 \n"					\
1103a72e3ebSJaroslaw Pelczar 	    "mrs %0, par_el1" : "=r"(ret) : "r"(addr));		\
1113a72e3ebSJaroslaw Pelczar 														\
1123a72e3ebSJaroslaw Pelczar 	return (ret);										\
1133a72e3ebSJaroslaw Pelczar }
1143a72e3ebSJaroslaw Pelczar 
115d1c3213aSmilek7 
1163a72e3ebSJaroslaw Pelczar ADDRESS_TRANSLATE_FUNC(s1e0r)
1173a72e3ebSJaroslaw Pelczar ADDRESS_TRANSLATE_FUNC(s1e0w)
1183a72e3ebSJaroslaw Pelczar ADDRESS_TRANSLATE_FUNC(s1e1r)
1193a72e3ebSJaroslaw Pelczar ADDRESS_TRANSLATE_FUNC(s1e1w)
1203a72e3ebSJaroslaw Pelczar 
121d1c3213aSmilek7 
122d1c3213aSmilek7 struct aarch64_fpu_state
123d1c3213aSmilek7 {
124d1c3213aSmilek7 	uint64 regs[32 * 2];
125d1c3213aSmilek7 	uint64 fpsr;
126d1c3213aSmilek7 	uint64 fpcr;
127d1c3213aSmilek7 };
128d1c3213aSmilek7 
129d1c3213aSmilek7 
1303a72e3ebSJaroslaw Pelczar /* raw exception frames */
1313a72e3ebSJaroslaw Pelczar struct iframe {
132d1c3213aSmilek7 	// return info
1333a72e3ebSJaroslaw Pelczar 	uint64 elr;
134d1c3213aSmilek7 	uint64 spsr;
135*c2f3786aSOwen Anderson 	uint64 x[29];
136*c2f3786aSOwen Anderson 	uint64 fp;
137d1c3213aSmilek7 	uint64 lr;
138d1c3213aSmilek7 	uint64 sp;
139d1c3213aSmilek7 
140d1c3213aSmilek7 	// exception info
141d1c3213aSmilek7 	uint64 esr;
142d1c3213aSmilek7 	uint64 far;
14306fae14eSmilek7 
14406fae14eSmilek7 	// fpu
14506fae14eSmilek7 	struct aarch64_fpu_state fpu;
1463a72e3ebSJaroslaw Pelczar };
1473a72e3ebSJaroslaw Pelczar 
148d1c3213aSmilek7 
1491761cb8eSJaroslaw Pelczar #ifdef __cplusplus
1503a72e3ebSJaroslaw Pelczar namespace BKernel {
1513a72e3ebSJaroslaw Pelczar 	struct Thread;
1523a72e3ebSJaroslaw Pelczar }  // namespace BKernel
1533a72e3ebSJaroslaw Pelczar 
154d1c3213aSmilek7 
1553a72e3ebSJaroslaw Pelczar typedef struct arch_cpu_info {
1563a72e3ebSJaroslaw Pelczar 	uint32						mpidr;
1573a72e3ebSJaroslaw Pelczar 	BKernel::Thread*			last_vfp_user;
1583a72e3ebSJaroslaw Pelczar } arch_cpu_info;
1591761cb8eSJaroslaw Pelczar #endif
1603a72e3ebSJaroslaw Pelczar 
161d1c3213aSmilek7 
1623a72e3ebSJaroslaw Pelczar #ifdef __cplusplus
1633a72e3ebSJaroslaw Pelczar extern "C" {
1643a72e3ebSJaroslaw Pelczar #endif
1653a72e3ebSJaroslaw Pelczar 
166d1c3213aSmilek7 
arch_cpu_pause(void)1673a72e3ebSJaroslaw Pelczar static inline void arch_cpu_pause(void)
1683a72e3ebSJaroslaw Pelczar {
1693a72e3ebSJaroslaw Pelczar 	arm64_yield();
1703a72e3ebSJaroslaw Pelczar }
1713a72e3ebSJaroslaw Pelczar 
172d1c3213aSmilek7 
arch_cpu_idle(void)1733a72e3ebSJaroslaw Pelczar static inline void arch_cpu_idle(void)
1743a72e3ebSJaroslaw Pelczar {
1756034ee94Smilek7 	arm64_wfi();
1763a72e3ebSJaroslaw Pelczar }
1773a72e3ebSJaroslaw Pelczar 
178d1c3213aSmilek7 
179303283fbSDavid Karoly extern addr_t arm64_get_fp(void);
180303283fbSDavid Karoly 
181303283fbSDavid Karoly 
1823a72e3ebSJaroslaw Pelczar #ifdef __cplusplus
1833a72e3ebSJaroslaw Pelczar }
1843a72e3ebSJaroslaw Pelczar #endif
1853a72e3ebSJaroslaw Pelczar 
1863a72e3ebSJaroslaw Pelczar #endif
1873a72e3ebSJaroslaw Pelczar 
1883a72e3ebSJaroslaw Pelczar 
1893a72e3ebSJaroslaw Pelczar #endif /* _KERNEL_ARCH_ARM64_ARCH_CPU_H_ */
190