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