/* * Copyright 2018, Jaroslaw Pelczar * Distributed under the terms of the MIT License. */ #ifndef _KERNEL_ARCH_ARM64_ARCH_CPU_H_ #define _KERNEL_ARCH_ARM64_ARCH_CPU_H_ #define CPU_MAX_CACHE_LEVEL 8 #define CACHE_LINE_SIZE 64 #define set_ac() #define clear_ac() #include #ifndef _ASSEMBLER #include #include #define arm64_sev() __asm__ __volatile__("sev" : : : "memory") #define arm64_wfe() __asm__ __volatile__("wfe" : : : "memory") #define arm64_dsb() __asm__ __volatile__("dsb" : : : "memory") #define arm64_dmb() __asm__ __volatile__("dmb" : : : "memory") #define arm64_isb() __asm__ __volatile__("isb" : : : "memory") #define arm64_nop() __asm__ __volatile__("nop" : : : "memory") #define arm64_yield() __asm__ __volatile__("yield" : : : "memory") /* Extract CPU affinity levels 0-3 */ #define CPU_AFF0(mpidr) (u_int)(((mpidr) >> 0) & 0xff) #define CPU_AFF1(mpidr) (u_int)(((mpidr) >> 8) & 0xff) #define CPU_AFF2(mpidr) (u_int)(((mpidr) >> 16) & 0xff) #define CPU_AFF3(mpidr) (u_int)(((mpidr) >> 32) & 0xff) #define CPU_AFF0_MASK 0xffUL #define CPU_AFF1_MASK 0xff00UL #define CPU_AFF2_MASK 0xff0000UL #define CPU_AFF3_MASK 0xff00000000UL #define CPU_AFF_MASK (CPU_AFF0_MASK | CPU_AFF1_MASK | \ CPU_AFF2_MASK| CPU_AFF3_MASK) /* Mask affinity fields in MPIDR_EL1 */ #define CPU_IMPL_ARM 0x41 #define CPU_IMPL_BROADCOM 0x42 #define CPU_IMPL_CAVIUM 0x43 #define CPU_IMPL_DEC 0x44 #define CPU_IMPL_INFINEON 0x49 #define CPU_IMPL_FREESCALE 0x4D #define CPU_IMPL_NVIDIA 0x4E #define CPU_IMPL_APM 0x50 #define CPU_IMPL_QUALCOMM 0x51 #define CPU_IMPL_MARVELL 0x56 #define CPU_IMPL_INTEL 0x69 #define CPU_PART_THUNDER 0x0A1 #define CPU_PART_FOUNDATION 0xD00 #define CPU_PART_CORTEX_A35 0xD04 #define CPU_PART_CORTEX_A53 0xD03 #define CPU_PART_CORTEX_A55 0xD05 #define CPU_PART_CORTEX_A57 0xD07 #define CPU_PART_CORTEX_A72 0xD08 #define CPU_PART_CORTEX_A73 0xD09 #define CPU_PART_CORTEX_A75 0xD0A #define CPU_REV_THUNDER_1_0 0x00 #define CPU_REV_THUNDER_1_1 0x01 #define CPU_IMPL(midr) (((midr) >> 24) & 0xff) #define CPU_PART(midr) (((midr) >> 4) & 0xfff) #define CPU_VAR(midr) (((midr) >> 20) & 0xf) #define CPU_REV(midr) (((midr) >> 0) & 0xf) #define CPU_IMPL_TO_MIDR(val) (((val) & 0xff) << 24) #define CPU_PART_TO_MIDR(val) (((val) & 0xfff) << 4) #define CPU_VAR_TO_MIDR(val) (((val) & 0xf) << 20) #define CPU_REV_TO_MIDR(val) (((val) & 0xf) << 0) #define CPU_IMPL_MASK (0xff << 24) #define CPU_PART_MASK (0xfff << 4) #define CPU_VAR_MASK (0xf << 20) #define CPU_REV_MASK (0xf << 0) #define CPU_ID_RAW(impl, part, var, rev) \ (CPU_IMPL_TO_MIDR((impl)) | \ CPU_PART_TO_MIDR((part)) | CPU_VAR_TO_MIDR((var)) | \ CPU_REV_TO_MIDR((rev))) #define CPU_MATCH(mask, impl, part, var, rev) \ (((mask) & PCPU_GET(midr)) == \ ((mask) & CPU_ID_RAW((impl), (part), (var), (rev)))) #define CPU_MATCH_RAW(mask, devid) \ (((mask) & PCPU_GET(midr)) == ((mask) & (devid))) static inline uint64 arm64_get_cyclecount(void) { return READ_SPECIALREG(cntvct_el0); } #define ADDRESS_TRANSLATE_FUNC(stage) \ static inline uint64 \ arm64_address_translate_ ##stage (uint64 addr) \ { \ uint64 ret; \ \ __asm __volatile( \ "at " __ARMREG_STRING(stage) ", %1 \n" \ "mrs %0, par_el1" : "=r"(ret) : "r"(addr)); \ \ return (ret); \ } ADDRESS_TRANSLATE_FUNC(s1e0r) ADDRESS_TRANSLATE_FUNC(s1e0w) ADDRESS_TRANSLATE_FUNC(s1e1r) ADDRESS_TRANSLATE_FUNC(s1e1w) struct aarch64_fpu_state { uint64 regs[32 * 2]; uint64 fpsr; uint64 fpcr; }; /* raw exception frames */ struct iframe { // return info uint64 elr; uint64 spsr; uint64 x[20]; uint64 lr; uint64 sp; uint64 fp; // exception info uint64 esr; uint64 far; }; #ifdef __cplusplus namespace BKernel { struct Thread; } // namespace BKernel typedef struct arch_cpu_info { uint32 mpidr; BKernel::Thread* last_vfp_user; } arch_cpu_info; #endif #ifdef __cplusplus extern "C" { #endif static inline void arch_cpu_pause(void) { arm64_yield(); } static inline void arch_cpu_idle(void) { arm64_yield(); } extern addr_t arm64_get_fp(void); #ifdef __cplusplus } #endif #endif #endif /* _KERNEL_ARCH_ARM64_ARCH_CPU_H_ */