xref: /openbmc/qemu/linux-user/arm/elfload.c (revision 3bf5c57a11827d9fa706524d57ee3e5af68a429e)
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