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