1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 3 #include "qemu/osdep.h" 4 #include "qemu.h" 5 #include "loader.h" 6 #include "user-internals.h" 7 #include "target_elf.h" 8 #include "target/arm/cpu-features.h" 9 #include "target_elf.h" 10 #include "elf.h" 11 12 13 const char *get_elf_cpu_model(uint32_t eflags) 14 { 15 return "any"; 16 } 17 18 enum 19 { 20 ARM_HWCAP_ARM_SWP = 1 << 0, 21 ARM_HWCAP_ARM_HALF = 1 << 1, 22 ARM_HWCAP_ARM_THUMB = 1 << 2, 23 ARM_HWCAP_ARM_26BIT = 1 << 3, 24 ARM_HWCAP_ARM_FAST_MULT = 1 << 4, 25 ARM_HWCAP_ARM_FPA = 1 << 5, 26 ARM_HWCAP_ARM_VFP = 1 << 6, 27 ARM_HWCAP_ARM_EDSP = 1 << 7, 28 ARM_HWCAP_ARM_JAVA = 1 << 8, 29 ARM_HWCAP_ARM_IWMMXT = 1 << 9, 30 ARM_HWCAP_ARM_CRUNCH = 1 << 10, 31 ARM_HWCAP_ARM_THUMBEE = 1 << 11, 32 ARM_HWCAP_ARM_NEON = 1 << 12, 33 ARM_HWCAP_ARM_VFPv3 = 1 << 13, 34 ARM_HWCAP_ARM_VFPv3D16 = 1 << 14, 35 ARM_HWCAP_ARM_TLS = 1 << 15, 36 ARM_HWCAP_ARM_VFPv4 = 1 << 16, 37 ARM_HWCAP_ARM_IDIVA = 1 << 17, 38 ARM_HWCAP_ARM_IDIVT = 1 << 18, 39 ARM_HWCAP_ARM_VFPD32 = 1 << 19, 40 ARM_HWCAP_ARM_LPAE = 1 << 20, 41 ARM_HWCAP_ARM_EVTSTRM = 1 << 21, 42 ARM_HWCAP_ARM_FPHP = 1 << 22, 43 ARM_HWCAP_ARM_ASIMDHP = 1 << 23, 44 ARM_HWCAP_ARM_ASIMDDP = 1 << 24, 45 ARM_HWCAP_ARM_ASIMDFHM = 1 << 25, 46 ARM_HWCAP_ARM_ASIMDBF16 = 1 << 26, 47 ARM_HWCAP_ARM_I8MM = 1 << 27, 48 }; 49 50 enum { 51 ARM_HWCAP2_ARM_AES = 1 << 0, 52 ARM_HWCAP2_ARM_PMULL = 1 << 1, 53 ARM_HWCAP2_ARM_SHA1 = 1 << 2, 54 ARM_HWCAP2_ARM_SHA2 = 1 << 3, 55 ARM_HWCAP2_ARM_CRC32 = 1 << 4, 56 ARM_HWCAP2_ARM_SB = 1 << 5, 57 ARM_HWCAP2_ARM_SSBS = 1 << 6, 58 }; 59 60 abi_ulong get_elf_hwcap(CPUState *cs) 61 { 62 ARMCPU *cpu = ARM_CPU(cs); 63 abi_ulong hwcaps = 0; 64 65 hwcaps |= ARM_HWCAP_ARM_SWP; 66 hwcaps |= ARM_HWCAP_ARM_HALF; 67 hwcaps |= ARM_HWCAP_ARM_THUMB; 68 hwcaps |= ARM_HWCAP_ARM_FAST_MULT; 69 70 /* probe for the extra features */ 71 #define GET_FEATURE(feat, hwcap) \ 72 do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) 73 74 #define GET_FEATURE_ID(feat, hwcap) \ 75 do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) 76 77 /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */ 78 GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP); 79 GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE); 80 GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON); 81 GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS); 82 GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE); 83 GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA); 84 GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT); 85 GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP); 86 87 if (cpu_isar_feature(aa32_fpsp_v3, cpu) || 88 cpu_isar_feature(aa32_fpdp_v3, cpu)) { 89 hwcaps |= ARM_HWCAP_ARM_VFPv3; 90 if (cpu_isar_feature(aa32_simd_r32, cpu)) { 91 hwcaps |= ARM_HWCAP_ARM_VFPD32; 92 } else { 93 hwcaps |= ARM_HWCAP_ARM_VFPv3D16; 94 } 95 } 96 GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4); 97 /* 98 * MVFR1.FPHP and .SIMDHP must be in sync, and QEMU uses the same 99 * isar_feature function for both. The kernel reports them as two hwcaps. 100 */ 101 GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_FPHP); 102 GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_ASIMDHP); 103 GET_FEATURE_ID(aa32_dp, ARM_HWCAP_ARM_ASIMDDP); 104 GET_FEATURE_ID(aa32_fhm, ARM_HWCAP_ARM_ASIMDFHM); 105 GET_FEATURE_ID(aa32_bf16, ARM_HWCAP_ARM_ASIMDBF16); 106 GET_FEATURE_ID(aa32_i8mm, ARM_HWCAP_ARM_I8MM); 107 108 return hwcaps; 109 } 110 111 abi_ulong get_elf_hwcap2(CPUState *cs) 112 { 113 ARMCPU *cpu = ARM_CPU(cs); 114 abi_ulong hwcaps = 0; 115 116 GET_FEATURE_ID(aa32_aes, ARM_HWCAP2_ARM_AES); 117 GET_FEATURE_ID(aa32_pmull, ARM_HWCAP2_ARM_PMULL); 118 GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1); 119 GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2); 120 GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32); 121 GET_FEATURE_ID(aa32_sb, ARM_HWCAP2_ARM_SB); 122 GET_FEATURE_ID(aa32_ssbs, ARM_HWCAP2_ARM_SSBS); 123 return hwcaps; 124 } 125 126 const char *elf_hwcap_str(uint32_t bit) 127 { 128 static const char *hwcap_str[] = { 129 [__builtin_ctz(ARM_HWCAP_ARM_SWP )] = "swp", 130 [__builtin_ctz(ARM_HWCAP_ARM_HALF )] = "half", 131 [__builtin_ctz(ARM_HWCAP_ARM_THUMB )] = "thumb", 132 [__builtin_ctz(ARM_HWCAP_ARM_26BIT )] = "26bit", 133 [__builtin_ctz(ARM_HWCAP_ARM_FAST_MULT)] = "fast_mult", 134 [__builtin_ctz(ARM_HWCAP_ARM_FPA )] = "fpa", 135 [__builtin_ctz(ARM_HWCAP_ARM_VFP )] = "vfp", 136 [__builtin_ctz(ARM_HWCAP_ARM_EDSP )] = "edsp", 137 [__builtin_ctz(ARM_HWCAP_ARM_JAVA )] = "java", 138 [__builtin_ctz(ARM_HWCAP_ARM_IWMMXT )] = "iwmmxt", 139 [__builtin_ctz(ARM_HWCAP_ARM_CRUNCH )] = "crunch", 140 [__builtin_ctz(ARM_HWCAP_ARM_THUMBEE )] = "thumbee", 141 [__builtin_ctz(ARM_HWCAP_ARM_NEON )] = "neon", 142 [__builtin_ctz(ARM_HWCAP_ARM_VFPv3 )] = "vfpv3", 143 [__builtin_ctz(ARM_HWCAP_ARM_VFPv3D16 )] = "vfpv3d16", 144 [__builtin_ctz(ARM_HWCAP_ARM_TLS )] = "tls", 145 [__builtin_ctz(ARM_HWCAP_ARM_VFPv4 )] = "vfpv4", 146 [__builtin_ctz(ARM_HWCAP_ARM_IDIVA )] = "idiva", 147 [__builtin_ctz(ARM_HWCAP_ARM_IDIVT )] = "idivt", 148 [__builtin_ctz(ARM_HWCAP_ARM_VFPD32 )] = "vfpd32", 149 [__builtin_ctz(ARM_HWCAP_ARM_LPAE )] = "lpae", 150 [__builtin_ctz(ARM_HWCAP_ARM_EVTSTRM )] = "evtstrm", 151 [__builtin_ctz(ARM_HWCAP_ARM_FPHP )] = "fphp", 152 [__builtin_ctz(ARM_HWCAP_ARM_ASIMDHP )] = "asimdhp", 153 [__builtin_ctz(ARM_HWCAP_ARM_ASIMDDP )] = "asimddp", 154 [__builtin_ctz(ARM_HWCAP_ARM_ASIMDFHM )] = "asimdfhm", 155 [__builtin_ctz(ARM_HWCAP_ARM_ASIMDBF16)] = "asimdbf16", 156 [__builtin_ctz(ARM_HWCAP_ARM_I8MM )] = "i8mm", 157 }; 158 159 return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; 160 } 161 162 const char *elf_hwcap2_str(uint32_t bit) 163 { 164 static const char *hwcap_str[] = { 165 [__builtin_ctz(ARM_HWCAP2_ARM_AES )] = "aes", 166 [__builtin_ctz(ARM_HWCAP2_ARM_PMULL)] = "pmull", 167 [__builtin_ctz(ARM_HWCAP2_ARM_SHA1 )] = "sha1", 168 [__builtin_ctz(ARM_HWCAP2_ARM_SHA2 )] = "sha2", 169 [__builtin_ctz(ARM_HWCAP2_ARM_CRC32)] = "crc32", 170 [__builtin_ctz(ARM_HWCAP2_ARM_SB )] = "sb", 171 [__builtin_ctz(ARM_HWCAP2_ARM_SSBS )] = "ssbs", 172 }; 173 174 return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; 175 } 176 177 const char *get_elf_platform(CPUState *cs) 178 { 179 CPUARMState *env = cpu_env(cs); 180 181 #if TARGET_BIG_ENDIAN 182 # define END "b" 183 #else 184 # define END "l" 185 #endif 186 187 if (arm_feature(env, ARM_FEATURE_V8)) { 188 return "v8" END; 189 } else if (arm_feature(env, ARM_FEATURE_V7)) { 190 if (arm_feature(env, ARM_FEATURE_M)) { 191 return "v7m" END; 192 } else { 193 return "v7" END; 194 } 195 } else if (arm_feature(env, ARM_FEATURE_V6)) { 196 return "v6" END; 197 } else if (arm_feature(env, ARM_FEATURE_V5)) { 198 return "v5" END; 199 } else { 200 return "v4" END; 201 } 202 203 #undef END 204 } 205 206 bool init_guest_commpage(void) 207 { 208 ARMCPU *cpu = ARM_CPU(thread_cpu); 209 int host_page_size = qemu_real_host_page_size(); 210 abi_ptr commpage; 211 void *want; 212 void *addr; 213 214 /* 215 * M-profile allocates maximum of 2GB address space, so can never 216 * allocate the commpage. Skip it. 217 */ 218 if (arm_feature(&cpu->env, ARM_FEATURE_M)) { 219 return true; 220 } 221 222 commpage = HI_COMMPAGE & -host_page_size; 223 want = g2h_untagged(commpage); 224 addr = mmap(want, host_page_size, PROT_READ | PROT_WRITE, 225 MAP_ANONYMOUS | MAP_PRIVATE | 226 (commpage < reserved_va ? MAP_FIXED : MAP_FIXED_NOREPLACE), 227 -1, 0); 228 229 if (addr == MAP_FAILED) { 230 perror("Allocating guest commpage"); 231 exit(EXIT_FAILURE); 232 } 233 if (addr != want) { 234 return false; 235 } 236 237 /* Set kernel helper versions; rest of page is 0. */ 238 __put_user(5, (uint32_t *)g2h_untagged(0xffff0ffcu)); 239 240 if (mprotect(addr, host_page_size, PROT_READ)) { 241 perror("Protecting guest commpage"); 242 exit(EXIT_FAILURE); 243 } 244 245 page_set_flags(commpage, commpage | (host_page_size - 1), 246 PAGE_READ | PAGE_EXEC | PAGE_VALID, PAGE_VALID); 247 return true; 248 } 249 250 void elf_core_copy_regs(target_elf_gregset_t *r, const CPUARMState *env) 251 { 252 for (int i = 0; i < 16; ++i) { 253 r->pt.regs[i] = tswapal(env->regs[i]); 254 } 255 r->pt.cpsr = tswapal(cpsr_read((CPUARMState *)env)); 256 r->pt.orig_r0 = tswapal(env->regs[0]); /* FIXME */ 257 } 258 259 #if TARGET_BIG_ENDIAN 260 # include "vdso-be8.c.inc" 261 # include "vdso-be32.c.inc" 262 #else 263 # include "vdso-le.c.inc" 264 #endif 265 266 const VdsoImageInfo *get_vdso_image_info(uint32_t elf_flags) 267 { 268 #if TARGET_BIG_ENDIAN 269 return (EF_ARM_EABI_VERSION(elf_flags) >= EF_ARM_EABI_VER4 270 && (elf_flags & EF_ARM_BE8) 271 ? &vdso_be8_image_info 272 : &vdso_be32_image_info); 273 #else 274 return &vdso_image_info; 275 #endif 276 } 277