diff options
Diffstat (limited to 'linux-user/elfload.c')
| -rw-r--r-- | linux-user/elfload.c | 2145 |
1 files changed, 61 insertions, 2084 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c index ea214105ff..26c090c95d 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -28,6 +28,7 @@ #include "qemu/lockable.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "target_elf.h" #include "target_signal.h" #include "tcg/debuginfo.h" @@ -35,29 +36,10 @@ #include "target/arm/cpu-features.h" #endif -#ifdef _ARCH_PPC64 -#undef ARCH_DLINFO -#undef ELF_PLATFORM -#undef ELF_HWCAP -#undef ELF_HWCAP2 -#undef ELF_CLASS -#undef ELF_DATA -#undef ELF_ARCH -#endif - #ifndef TARGET_ARCH_HAS_SIGTRAMP_PAGE #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0 #endif -typedef struct { - const uint8_t *image; - const uint32_t *relocs; - unsigned image_size; - unsigned reloc_count; - unsigned sigreturn_ofs; - unsigned rt_sigreturn_ofs; -} VdsoImageInfo; - #define ELF_OSABI ELFOSABI_SYSV /* from personality.h */ @@ -123,30 +105,12 @@ int info_is_fdpic(struct image_info *info) return info->personality == PER_LINUX_FDPIC; } -/* this flag is uneffective under linux too, should be deleted */ -#ifndef MAP_DENYWRITE -#define MAP_DENYWRITE 0 -#endif - -/* should probably go in elf.h */ -#ifndef ELIBBAD -#define ELIBBAD 80 -#endif - #if TARGET_BIG_ENDIAN #define ELF_DATA ELFDATA2MSB #else #define ELF_DATA ELFDATA2LSB #endif -#ifdef TARGET_ABI_MIPSN32 -typedef abi_ullong target_elf_greg_t; -#define tswapreg(ptr) tswap64(ptr) -#else -typedef abi_ulong target_elf_greg_t; -#define tswapreg(ptr) tswapal(ptr) -#endif - #ifdef USE_UID16 typedef abi_ushort target_uid_t; typedef abi_ushort target_gid_t; @@ -156,1970 +120,14 @@ typedef abi_uint target_gid_t; #endif typedef abi_int target_pid_t; -#ifdef TARGET_I386 - -#define ELF_HWCAP get_elf_hwcap() - -static uint32_t get_elf_hwcap(void) -{ - X86CPU *cpu = X86_CPU(thread_cpu); - - return cpu->env.features[FEAT_1_EDX]; -} - -#ifdef TARGET_X86_64 -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_X86_64 - -#define ELF_PLATFORM "x86_64" - -static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) -{ - regs->rax = 0; - regs->rsp = infop->start_stack; - regs->rip = infop->entry; -} - -#define ELF_NREG 27 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -/* - * Note that ELF_NREG should be 29 as there should be place for - * TRAPNO and ERR "registers" as well but linux doesn't dump - * those. - * - * See linux kernel: arch/x86/include/asm/elf.h - */ -static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) -{ - (*regs)[0] = tswapreg(env->regs[15]); - (*regs)[1] = tswapreg(env->regs[14]); - (*regs)[2] = tswapreg(env->regs[13]); - (*regs)[3] = tswapreg(env->regs[12]); - (*regs)[4] = tswapreg(env->regs[R_EBP]); - (*regs)[5] = tswapreg(env->regs[R_EBX]); - (*regs)[6] = tswapreg(env->regs[11]); - (*regs)[7] = tswapreg(env->regs[10]); - (*regs)[8] = tswapreg(env->regs[9]); - (*regs)[9] = tswapreg(env->regs[8]); - (*regs)[10] = tswapreg(env->regs[R_EAX]); - (*regs)[11] = tswapreg(env->regs[R_ECX]); - (*regs)[12] = tswapreg(env->regs[R_EDX]); - (*regs)[13] = tswapreg(env->regs[R_ESI]); - (*regs)[14] = tswapreg(env->regs[R_EDI]); - (*regs)[15] = tswapreg(get_task_state(env_cpu_const(env))->orig_ax); - (*regs)[16] = tswapreg(env->eip); - (*regs)[17] = tswapreg(env->segs[R_CS].selector & 0xffff); - (*regs)[18] = tswapreg(env->eflags); - (*regs)[19] = tswapreg(env->regs[R_ESP]); - (*regs)[20] = tswapreg(env->segs[R_SS].selector & 0xffff); - (*regs)[21] = tswapreg(env->segs[R_FS].selector & 0xffff); - (*regs)[22] = tswapreg(env->segs[R_GS].selector & 0xffff); - (*regs)[23] = tswapreg(env->segs[R_DS].selector & 0xffff); - (*regs)[24] = tswapreg(env->segs[R_ES].selector & 0xffff); - (*regs)[25] = tswapreg(env->segs[R_FS].selector & 0xffff); - (*regs)[26] = tswapreg(env->segs[R_GS].selector & 0xffff); -} - -#if ULONG_MAX > UINT32_MAX -#define INIT_GUEST_COMMPAGE -static bool init_guest_commpage(void) -{ - /* - * The vsyscall page is at a high negative address aka kernel space, - * which means that we cannot actually allocate it with target_mmap. - * We still should be able to use page_set_flags, unless the user - * has specified -R reserved_va, which would trigger an assert(). - */ - if (reserved_va != 0 && - TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE - 1 > reserved_va) { - error_report("Cannot allocate vsyscall page"); - exit(EXIT_FAILURE); - } - page_set_flags(TARGET_VSYSCALL_PAGE, - TARGET_VSYSCALL_PAGE | ~TARGET_PAGE_MASK, - PAGE_EXEC | PAGE_VALID); - return true; -} -#endif -#else - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_386 - -#define ELF_PLATFORM get_elf_platform() -#define EXSTACK_DEFAULT true - -static const char *get_elf_platform(void) -{ - static char elf_platform[] = "i386"; - int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL); - if (family > 6) { - family = 6; - } - if (family >= 3) { - elf_platform[1] = '0' + family; - } - return elf_platform; -} - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->esp = infop->start_stack; - regs->eip = infop->entry; - - /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program - starts %edx contains a pointer to a function which might be - registered using `atexit'. This provides a mean for the - dynamic linker to call DT_FINI functions for shared libraries - that have been loaded before the code runs. - - A value of 0 tells we have no such handler. */ - regs->edx = 0; -} - -#define ELF_NREG 17 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -/* - * Note that ELF_NREG should be 19 as there should be place for - * TRAPNO and ERR "registers" as well but linux doesn't dump - * those. - * - * See linux kernel: arch/x86/include/asm/elf.h - */ -static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) -{ - (*regs)[0] = tswapreg(env->regs[R_EBX]); - (*regs)[1] = tswapreg(env->regs[R_ECX]); - (*regs)[2] = tswapreg(env->regs[R_EDX]); - (*regs)[3] = tswapreg(env->regs[R_ESI]); - (*regs)[4] = tswapreg(env->regs[R_EDI]); - (*regs)[5] = tswapreg(env->regs[R_EBP]); - (*regs)[6] = tswapreg(env->regs[R_EAX]); - (*regs)[7] = tswapreg(env->segs[R_DS].selector & 0xffff); - (*regs)[8] = tswapreg(env->segs[R_ES].selector & 0xffff); - (*regs)[9] = tswapreg(env->segs[R_FS].selector & 0xffff); - (*regs)[10] = tswapreg(env->segs[R_GS].selector & 0xffff); - (*regs)[11] = tswapreg(get_task_state(env_cpu_const(env))->orig_ax); - (*regs)[12] = tswapreg(env->eip); - (*regs)[13] = tswapreg(env->segs[R_CS].selector & 0xffff); - (*regs)[14] = tswapreg(env->eflags); - (*regs)[15] = tswapreg(env->regs[R_ESP]); - (*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff); -} - -/* - * i386 is the only target which supplies AT_SYSINFO for the vdso. - * All others only supply AT_SYSINFO_EHDR. - */ -#define DLINFO_ARCH_ITEMS (vdso_info != NULL) -#define ARCH_DLINFO \ - do { \ - if (vdso_info) { \ - NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry); \ - } \ - } while (0) - -#endif /* TARGET_X86_64 */ - -#define VDSO_HEADER "vdso.c.inc" - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -#endif /* TARGET_I386 */ - -#ifdef TARGET_ARM - -#ifndef TARGET_AARCH64 -/* 32 bit ARM definitions */ - -#define ELF_ARCH EM_ARM -#define ELF_CLASS ELFCLASS32 -#define EXSTACK_DEFAULT true - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - abi_long stack = infop->start_stack; - memset(regs, 0, sizeof(*regs)); - - regs->uregs[16] = ARM_CPU_MODE_USR; - if (infop->entry & 1) { - regs->uregs[16] |= CPSR_T; - } - regs->uregs[15] = infop->entry & 0xfffffffe; - regs->uregs[13] = infop->start_stack; - /* FIXME - what to for failure of get_user()? */ - get_user_ual(regs->uregs[2], stack + 8); /* envp */ - get_user_ual(regs->uregs[1], stack + 4); /* envp */ - /* XXX: it seems that r0 is zeroed after ! */ - regs->uregs[0] = 0; - /* For uClinux PIC binaries. */ - /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ - regs->uregs[10] = infop->start_data; - - /* Support ARM FDPIC. */ - if (info_is_fdpic(infop)) { - /* As described in the ABI document, r7 points to the loadmap info - * prepared by the kernel. If an interpreter is needed, r8 points - * to the interpreter loadmap and r9 points to the interpreter - * PT_DYNAMIC info. If no interpreter is needed, r8 is zero, and - * r9 points to the main program PT_DYNAMIC info. - */ - regs->uregs[7] = infop->loadmap_addr; - if (infop->interpreter_loadmap_addr) { - /* Executable is dynamically loaded. */ - regs->uregs[8] = infop->interpreter_loadmap_addr; - regs->uregs[9] = infop->interpreter_pt_dynamic_addr; - } else { - regs->uregs[8] = 0; - regs->uregs[9] = infop->pt_dynamic_addr; - } - } -} - -#define ELF_NREG 18 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env) -{ - (*regs)[0] = tswapreg(env->regs[0]); - (*regs)[1] = tswapreg(env->regs[1]); - (*regs)[2] = tswapreg(env->regs[2]); - (*regs)[3] = tswapreg(env->regs[3]); - (*regs)[4] = tswapreg(env->regs[4]); - (*regs)[5] = tswapreg(env->regs[5]); - (*regs)[6] = tswapreg(env->regs[6]); - (*regs)[7] = tswapreg(env->regs[7]); - (*regs)[8] = tswapreg(env->regs[8]); - (*regs)[9] = tswapreg(env->regs[9]); - (*regs)[10] = tswapreg(env->regs[10]); - (*regs)[11] = tswapreg(env->regs[11]); - (*regs)[12] = tswapreg(env->regs[12]); - (*regs)[13] = tswapreg(env->regs[13]); - (*regs)[14] = tswapreg(env->regs[14]); - (*regs)[15] = tswapreg(env->regs[15]); - - (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env)); - (*regs)[17] = tswapreg(env->regs[0]); /* XXX */ -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -enum -{ - ARM_HWCAP_ARM_SWP = 1 << 0, - ARM_HWCAP_ARM_HALF = 1 << 1, - ARM_HWCAP_ARM_THUMB = 1 << 2, - ARM_HWCAP_ARM_26BIT = 1 << 3, - ARM_HWCAP_ARM_FAST_MULT = 1 << 4, - ARM_HWCAP_ARM_FPA = 1 << 5, - ARM_HWCAP_ARM_VFP = 1 << 6, - ARM_HWCAP_ARM_EDSP = 1 << 7, - ARM_HWCAP_ARM_JAVA = 1 << 8, - ARM_HWCAP_ARM_IWMMXT = 1 << 9, - ARM_HWCAP_ARM_CRUNCH = 1 << 10, - ARM_HWCAP_ARM_THUMBEE = 1 << 11, - ARM_HWCAP_ARM_NEON = 1 << 12, - ARM_HWCAP_ARM_VFPv3 = 1 << 13, - ARM_HWCAP_ARM_VFPv3D16 = 1 << 14, - ARM_HWCAP_ARM_TLS = 1 << 15, - ARM_HWCAP_ARM_VFPv4 = 1 << 16, - ARM_HWCAP_ARM_IDIVA = 1 << 17, - ARM_HWCAP_ARM_IDIVT = 1 << 18, - ARM_HWCAP_ARM_VFPD32 = 1 << 19, - ARM_HWCAP_ARM_LPAE = 1 << 20, - ARM_HWCAP_ARM_EVTSTRM = 1 << 21, - ARM_HWCAP_ARM_FPHP = 1 << 22, - ARM_HWCAP_ARM_ASIMDHP = 1 << 23, - ARM_HWCAP_ARM_ASIMDDP = 1 << 24, - ARM_HWCAP_ARM_ASIMDFHM = 1 << 25, - ARM_HWCAP_ARM_ASIMDBF16 = 1 << 26, - ARM_HWCAP_ARM_I8MM = 1 << 27, -}; - -enum { - ARM_HWCAP2_ARM_AES = 1 << 0, - ARM_HWCAP2_ARM_PMULL = 1 << 1, - ARM_HWCAP2_ARM_SHA1 = 1 << 2, - ARM_HWCAP2_ARM_SHA2 = 1 << 3, - ARM_HWCAP2_ARM_CRC32 = 1 << 4, - ARM_HWCAP2_ARM_SB = 1 << 5, - ARM_HWCAP2_ARM_SSBS = 1 << 6, -}; - -/* The commpage only exists for 32 bit kernels */ - -#define HI_COMMPAGE (intptr_t)0xffff0f00u - -static bool init_guest_commpage(void) -{ - ARMCPU *cpu = ARM_CPU(thread_cpu); - int host_page_size = qemu_real_host_page_size(); - abi_ptr commpage; - void *want; - void *addr; - - /* - * M-profile allocates maximum of 2GB address space, so can never - * allocate the commpage. Skip it. - */ - if (arm_feature(&cpu->env, ARM_FEATURE_M)) { - return true; - } - - commpage = HI_COMMPAGE & -host_page_size; - want = g2h_untagged(commpage); - addr = mmap(want, host_page_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE | - (commpage < reserved_va ? MAP_FIXED : MAP_FIXED_NOREPLACE), - -1, 0); - - if (addr == MAP_FAILED) { - perror("Allocating guest commpage"); - exit(EXIT_FAILURE); - } - if (addr != want) { - return false; - } - - /* Set kernel helper versions; rest of page is 0. */ - __put_user(5, (uint32_t *)g2h_untagged(0xffff0ffcu)); - - if (mprotect(addr, host_page_size, PROT_READ)) { - perror("Protecting guest commpage"); - exit(EXIT_FAILURE); - } - - page_set_flags(commpage, commpage | (host_page_size - 1), - PAGE_READ | PAGE_EXEC | PAGE_VALID); - return true; -} - -#define ELF_HWCAP get_elf_hwcap() -#define ELF_HWCAP2 get_elf_hwcap2() - -uint32_t get_elf_hwcap(void) -{ - ARMCPU *cpu = ARM_CPU(thread_cpu); - uint32_t hwcaps = 0; - - hwcaps |= ARM_HWCAP_ARM_SWP; - hwcaps |= ARM_HWCAP_ARM_HALF; - hwcaps |= ARM_HWCAP_ARM_THUMB; - hwcaps |= ARM_HWCAP_ARM_FAST_MULT; - - /* probe for the extra features */ -#define GET_FEATURE(feat, hwcap) \ - do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) - -#define GET_FEATURE_ID(feat, hwcap) \ - do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) - - /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */ - GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP); - GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT); - GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE); - GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON); - GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS); - GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE); - GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA); - GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT); - GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP); - - if (cpu_isar_feature(aa32_fpsp_v3, cpu) || - cpu_isar_feature(aa32_fpdp_v3, cpu)) { - hwcaps |= ARM_HWCAP_ARM_VFPv3; - if (cpu_isar_feature(aa32_simd_r32, cpu)) { - hwcaps |= ARM_HWCAP_ARM_VFPD32; - } else { - hwcaps |= ARM_HWCAP_ARM_VFPv3D16; - } - } - GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4); - /* - * MVFR1.FPHP and .SIMDHP must be in sync, and QEMU uses the same - * isar_feature function for both. The kernel reports them as two hwcaps. - */ - GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_FPHP); - GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_ASIMDHP); - GET_FEATURE_ID(aa32_dp, ARM_HWCAP_ARM_ASIMDDP); - GET_FEATURE_ID(aa32_fhm, ARM_HWCAP_ARM_ASIMDFHM); - GET_FEATURE_ID(aa32_bf16, ARM_HWCAP_ARM_ASIMDBF16); - GET_FEATURE_ID(aa32_i8mm, ARM_HWCAP_ARM_I8MM); - - return hwcaps; -} - -uint64_t get_elf_hwcap2(void) -{ - ARMCPU *cpu = ARM_CPU(thread_cpu); - uint64_t hwcaps = 0; - - GET_FEATURE_ID(aa32_aes, ARM_HWCAP2_ARM_AES); - GET_FEATURE_ID(aa32_pmull, ARM_HWCAP2_ARM_PMULL); - GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1); - GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2); - GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32); - GET_FEATURE_ID(aa32_sb, ARM_HWCAP2_ARM_SB); - GET_FEATURE_ID(aa32_ssbs, ARM_HWCAP2_ARM_SSBS); - return hwcaps; -} - -const char *elf_hwcap_str(uint32_t bit) -{ - static const char *hwcap_str[] = { - [__builtin_ctz(ARM_HWCAP_ARM_SWP )] = "swp", - [__builtin_ctz(ARM_HWCAP_ARM_HALF )] = "half", - [__builtin_ctz(ARM_HWCAP_ARM_THUMB )] = "thumb", - [__builtin_ctz(ARM_HWCAP_ARM_26BIT )] = "26bit", - [__builtin_ctz(ARM_HWCAP_ARM_FAST_MULT)] = "fast_mult", - [__builtin_ctz(ARM_HWCAP_ARM_FPA )] = "fpa", - [__builtin_ctz(ARM_HWCAP_ARM_VFP )] = "vfp", - [__builtin_ctz(ARM_HWCAP_ARM_EDSP )] = "edsp", - [__builtin_ctz(ARM_HWCAP_ARM_JAVA )] = "java", - [__builtin_ctz(ARM_HWCAP_ARM_IWMMXT )] = "iwmmxt", - [__builtin_ctz(ARM_HWCAP_ARM_CRUNCH )] = "crunch", - [__builtin_ctz(ARM_HWCAP_ARM_THUMBEE )] = "thumbee", - [__builtin_ctz(ARM_HWCAP_ARM_NEON )] = "neon", - [__builtin_ctz(ARM_HWCAP_ARM_VFPv3 )] = "vfpv3", - [__builtin_ctz(ARM_HWCAP_ARM_VFPv3D16 )] = "vfpv3d16", - [__builtin_ctz(ARM_HWCAP_ARM_TLS )] = "tls", - [__builtin_ctz(ARM_HWCAP_ARM_VFPv4 )] = "vfpv4", - [__builtin_ctz(ARM_HWCAP_ARM_IDIVA )] = "idiva", - [__builtin_ctz(ARM_HWCAP_ARM_IDIVT )] = "idivt", - [__builtin_ctz(ARM_HWCAP_ARM_VFPD32 )] = "vfpd32", - [__builtin_ctz(ARM_HWCAP_ARM_LPAE )] = "lpae", - [__builtin_ctz(ARM_HWCAP_ARM_EVTSTRM )] = "evtstrm", - [__builtin_ctz(ARM_HWCAP_ARM_FPHP )] = "fphp", - [__builtin_ctz(ARM_HWCAP_ARM_ASIMDHP )] = "asimdhp", - [__builtin_ctz(ARM_HWCAP_ARM_ASIMDDP )] = "asimddp", - [__builtin_ctz(ARM_HWCAP_ARM_ASIMDFHM )] = "asimdfhm", - [__builtin_ctz(ARM_HWCAP_ARM_ASIMDBF16)] = "asimdbf16", - [__builtin_ctz(ARM_HWCAP_ARM_I8MM )] = "i8mm", - }; - - return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; -} - -const char *elf_hwcap2_str(uint32_t bit) -{ - static const char *hwcap_str[] = { - [__builtin_ctz(ARM_HWCAP2_ARM_AES )] = "aes", - [__builtin_ctz(ARM_HWCAP2_ARM_PMULL)] = "pmull", - [__builtin_ctz(ARM_HWCAP2_ARM_SHA1 )] = "sha1", - [__builtin_ctz(ARM_HWCAP2_ARM_SHA2 )] = "sha2", - [__builtin_ctz(ARM_HWCAP2_ARM_CRC32)] = "crc32", - [__builtin_ctz(ARM_HWCAP2_ARM_SB )] = "sb", - [__builtin_ctz(ARM_HWCAP2_ARM_SSBS )] = "ssbs", - }; - - return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; -} - -#undef GET_FEATURE -#undef GET_FEATURE_ID - -#define ELF_PLATFORM get_elf_platform() - -static const char *get_elf_platform(void) -{ - CPUARMState *env = cpu_env(thread_cpu); - -#if TARGET_BIG_ENDIAN -# define END "b" -#else -# define END "l" -#endif - - if (arm_feature(env, ARM_FEATURE_V8)) { - return "v8" END; - } else if (arm_feature(env, ARM_FEATURE_V7)) { - if (arm_feature(env, ARM_FEATURE_M)) { - return "v7m" END; - } else { - return "v7" END; - } - } else if (arm_feature(env, ARM_FEATURE_V6)) { - return "v6" END; - } else if (arm_feature(env, ARM_FEATURE_V5)) { - return "v5" END; - } else { - return "v4" END; - } - -#undef END -} - -#if TARGET_BIG_ENDIAN -#include "elf.h" -#include "vdso-be8.c.inc" -#include "vdso-be32.c.inc" - -static const VdsoImageInfo *vdso_image_info(uint32_t elf_flags) -{ - return (EF_ARM_EABI_VERSION(elf_flags) >= EF_ARM_EABI_VER4 - && (elf_flags & EF_ARM_BE8) - ? &vdso_be8_image_info - : &vdso_be32_image_info); -} -#define vdso_image_info vdso_image_info -#else -# define VDSO_HEADER "vdso-le.c.inc" -#endif - -#else -/* 64 bit ARM definitions */ - -#define ELF_ARCH EM_AARCH64 -#define ELF_CLASS ELFCLASS64 -#if TARGET_BIG_ENDIAN -# define ELF_PLATFORM "aarch64_be" -#else -# define ELF_PLATFORM "aarch64" -#endif - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - abi_long stack = infop->start_stack; - memset(regs, 0, sizeof(*regs)); - - regs->pc = infop->entry & ~0x3ULL; - regs->sp = stack; -} - -#define ELF_NREG 34 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -static void elf_core_copy_regs(target_elf_gregset_t *regs, - const CPUARMState *env) -{ - int i; - - for (i = 0; i < 32; i++) { - (*regs)[i] = tswapreg(env->xregs[i]); - } - (*regs)[32] = tswapreg(env->pc); - (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env)); -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -enum { - ARM_HWCAP_A64_FP = 1 << 0, - ARM_HWCAP_A64_ASIMD = 1 << 1, - ARM_HWCAP_A64_EVTSTRM = 1 << 2, - ARM_HWCAP_A64_AES = 1 << 3, - ARM_HWCAP_A64_PMULL = 1 << 4, - ARM_HWCAP_A64_SHA1 = 1 << 5, - ARM_HWCAP_A64_SHA2 = 1 << 6, - ARM_HWCAP_A64_CRC32 = 1 << 7, - ARM_HWCAP_A64_ATOMICS = 1 << 8, - ARM_HWCAP_A64_FPHP = 1 << 9, - ARM_HWCAP_A64_ASIMDHP = 1 << 10, - ARM_HWCAP_A64_CPUID = 1 << 11, - ARM_HWCAP_A64_ASIMDRDM = 1 << 12, - ARM_HWCAP_A64_JSCVT = 1 << 13, - ARM_HWCAP_A64_FCMA = 1 << 14, - ARM_HWCAP_A64_LRCPC = 1 << 15, - ARM_HWCAP_A64_DCPOP = 1 << 16, - ARM_HWCAP_A64_SHA3 = 1 << 17, - ARM_HWCAP_A64_SM3 = 1 << 18, - ARM_HWCAP_A64_SM4 = 1 << 19, - ARM_HWCAP_A64_ASIMDDP = 1 << 20, - ARM_HWCAP_A64_SHA512 = 1 << 21, - ARM_HWCAP_A64_SVE = 1 << 22, - ARM_HWCAP_A64_ASIMDFHM = 1 << 23, - ARM_HWCAP_A64_DIT = 1 << 24, - ARM_HWCAP_A64_USCAT = 1 << 25, - ARM_HWCAP_A64_ILRCPC = 1 << 26, - ARM_HWCAP_A64_FLAGM = 1 << 27, - ARM_HWCAP_A64_SSBS = 1 << 28, - ARM_HWCAP_A64_SB = 1 << 29, - ARM_HWCAP_A64_PACA = 1 << 30, - ARM_HWCAP_A64_PACG = 1ULL << 31, - ARM_HWCAP_A64_GCS = 1ULL << 32, - ARM_HWCAP_A64_CMPBR = 1ULL << 33, - ARM_HWCAP_A64_FPRCVT = 1ULL << 34, - ARM_HWCAP_A64_F8MM8 = 1ULL << 35, - ARM_HWCAP_A64_F8MM4 = 1ULL << 36, - ARM_HWCAP_A64_SVE_F16MM = 1ULL << 37, - ARM_HWCAP_A64_SVE_ELTPERM = 1ULL << 38, - ARM_HWCAP_A64_SVE_AES2 = 1ULL << 39, - ARM_HWCAP_A64_SVE_BFSCALE = 1ULL << 40, - ARM_HWCAP_A64_SVE2P2 = 1ULL << 41, - ARM_HWCAP_A64_SME2P2 = 1ULL << 42, - ARM_HWCAP_A64_SME_SBITPERM = 1ULL << 43, - ARM_HWCAP_A64_SME_AES = 1ULL << 44, - ARM_HWCAP_A64_SME_SFEXPA = 1ULL << 45, - ARM_HWCAP_A64_SME_STMOP = 1ULL << 46, - ARM_HWCAP_A64_SME_SMOP4 = 1ULL << 47, - - ARM_HWCAP2_A64_DCPODP = 1 << 0, - ARM_HWCAP2_A64_SVE2 = 1 << 1, - ARM_HWCAP2_A64_SVEAES = 1 << 2, - ARM_HWCAP2_A64_SVEPMULL = 1 << 3, - ARM_HWCAP2_A64_SVEBITPERM = 1 << 4, - ARM_HWCAP2_A64_SVESHA3 = 1 << 5, - ARM_HWCAP2_A64_SVESM4 = 1 << 6, - ARM_HWCAP2_A64_FLAGM2 = 1 << 7, - ARM_HWCAP2_A64_FRINT = 1 << 8, - ARM_HWCAP2_A64_SVEI8MM = 1 << 9, - ARM_HWCAP2_A64_SVEF32MM = 1 << 10, - ARM_HWCAP2_A64_SVEF64MM = 1 << 11, - ARM_HWCAP2_A64_SVEBF16 = 1 << 12, - ARM_HWCAP2_A64_I8MM = 1 << 13, - ARM_HWCAP2_A64_BF16 = 1 << 14, - ARM_HWCAP2_A64_DGH = 1 << 15, - ARM_HWCAP2_A64_RNG = 1 << 16, - ARM_HWCAP2_A64_BTI = 1 << 17, - ARM_HWCAP2_A64_MTE = 1 << 18, - ARM_HWCAP2_A64_ECV = 1 << 19, - ARM_HWCAP2_A64_AFP = 1 << 20, - ARM_HWCAP2_A64_RPRES = 1 << 21, - ARM_HWCAP2_A64_MTE3 = 1 << 22, - ARM_HWCAP2_A64_SME = 1 << 23, - ARM_HWCAP2_A64_SME_I16I64 = 1 << 24, - ARM_HWCAP2_A64_SME_F64F64 = 1 << 25, - ARM_HWCAP2_A64_SME_I8I32 = 1 << 26, - ARM_HWCAP2_A64_SME_F16F32 = 1 << 27, - ARM_HWCAP2_A64_SME_B16F32 = 1 << 28, - ARM_HWCAP2_A64_SME_F32F32 = 1 << 29, - ARM_HWCAP2_A64_SME_FA64 = 1 << 30, - ARM_HWCAP2_A64_WFXT = 1ULL << 31, - ARM_HWCAP2_A64_EBF16 = 1ULL << 32, - ARM_HWCAP2_A64_SVE_EBF16 = 1ULL << 33, - ARM_HWCAP2_A64_CSSC = 1ULL << 34, - ARM_HWCAP2_A64_RPRFM = 1ULL << 35, - ARM_HWCAP2_A64_SVE2P1 = 1ULL << 36, - ARM_HWCAP2_A64_SME2 = 1ULL << 37, - ARM_HWCAP2_A64_SME2P1 = 1ULL << 38, - ARM_HWCAP2_A64_SME_I16I32 = 1ULL << 39, - ARM_HWCAP2_A64_SME_BI32I32 = 1ULL << 40, - ARM_HWCAP2_A64_SME_B16B16 = 1ULL << 41, - ARM_HWCAP2_A64_SME_F16F16 = 1ULL << 42, - ARM_HWCAP2_A64_MOPS = 1ULL << 43, - ARM_HWCAP2_A64_HBC = 1ULL << 44, - ARM_HWCAP2_A64_SVE_B16B16 = 1ULL << 45, - ARM_HWCAP2_A64_LRCPC3 = 1ULL << 46, - ARM_HWCAP2_A64_LSE128 = 1ULL << 47, - ARM_HWCAP2_A64_FPMR = 1ULL << 48, - ARM_HWCAP2_A64_LUT = 1ULL << 49, - ARM_HWCAP2_A64_FAMINMAX = 1ULL << 50, - ARM_HWCAP2_A64_F8CVT = 1ULL << 51, - ARM_HWCAP2_A64_F8FMA = 1ULL << 52, - ARM_HWCAP2_A64_F8DP4 = 1ULL << 53, - ARM_HWCAP2_A64_F8DP2 = 1ULL << 54, - ARM_HWCAP2_A64_F8E4M3 = 1ULL << 55, - ARM_HWCAP2_A64_F8E5M2 = 1ULL << 56, - ARM_HWCAP2_A64_SME_LUTV2 = 1ULL << 57, - ARM_HWCAP2_A64_SME_F8F16 = 1ULL << 58, - ARM_HWCAP2_A64_SME_F8F32 = 1ULL << 59, - ARM_HWCAP2_A64_SME_SF8FMA = 1ULL << 60, - ARM_HWCAP2_A64_SME_SF8DP4 = 1ULL << 61, - ARM_HWCAP2_A64_SME_SF8DP2 = 1ULL << 62, - ARM_HWCAP2_A64_POE = 1ULL << 63, -}; - -#define ELF_HWCAP get_elf_hwcap() -#define ELF_HWCAP2 get_elf_hwcap2() - -#define GET_FEATURE_ID(feat, hwcap) \ - do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) - -uint32_t get_elf_hwcap(void) -{ - ARMCPU *cpu = ARM_CPU(thread_cpu); - uint32_t hwcaps = 0; - - hwcaps |= ARM_HWCAP_A64_FP; - hwcaps |= ARM_HWCAP_A64_ASIMD; - hwcaps |= ARM_HWCAP_A64_CPUID; - - /* probe for the extra features */ - - GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES); - GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL); - GET_FEATURE_ID(aa64_sha1, ARM_HWCAP_A64_SHA1); - GET_FEATURE_ID(aa64_sha256, ARM_HWCAP_A64_SHA2); - GET_FEATURE_ID(aa64_sha512, ARM_HWCAP_A64_SHA512); - GET_FEATURE_ID(aa64_crc32, ARM_HWCAP_A64_CRC32); - GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3); - GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3); - GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4); - GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP); - GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS); - GET_FEATURE_ID(aa64_lse2, ARM_HWCAP_A64_USCAT); - GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM); - GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP); - GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA); - GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE); - GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG); - GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM); - GET_FEATURE_ID(aa64_dit, ARM_HWCAP_A64_DIT); - GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT); - GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB); - GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM); - GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP); - GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC); - GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC); - - return hwcaps; -} - -uint64_t get_elf_hwcap2(void) -{ - ARMCPU *cpu = ARM_CPU(thread_cpu); - uint64_t hwcaps = 0; - - GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP); - GET_FEATURE_ID(aa64_sve2, ARM_HWCAP2_A64_SVE2); - GET_FEATURE_ID(aa64_sve2_aes, ARM_HWCAP2_A64_SVEAES); - GET_FEATURE_ID(aa64_sve2_pmull128, ARM_HWCAP2_A64_SVEPMULL); - GET_FEATURE_ID(aa64_sve2_bitperm, ARM_HWCAP2_A64_SVEBITPERM); - GET_FEATURE_ID(aa64_sve2_sha3, ARM_HWCAP2_A64_SVESHA3); - GET_FEATURE_ID(aa64_sve2_sm4, ARM_HWCAP2_A64_SVESM4); - GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2); - GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT); - GET_FEATURE_ID(aa64_sve_i8mm, ARM_HWCAP2_A64_SVEI8MM); - GET_FEATURE_ID(aa64_sve_f32mm, ARM_HWCAP2_A64_SVEF32MM); - GET_FEATURE_ID(aa64_sve_f64mm, ARM_HWCAP2_A64_SVEF64MM); - GET_FEATURE_ID(aa64_sve_bf16, ARM_HWCAP2_A64_SVEBF16); - GET_FEATURE_ID(aa64_i8mm, ARM_HWCAP2_A64_I8MM); - GET_FEATURE_ID(aa64_bf16, ARM_HWCAP2_A64_BF16); - GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG); - GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI); - GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE); - GET_FEATURE_ID(aa64_mte3, ARM_HWCAP2_A64_MTE3); - GET_FEATURE_ID(aa64_sme, (ARM_HWCAP2_A64_SME | - ARM_HWCAP2_A64_SME_F32F32 | - ARM_HWCAP2_A64_SME_B16F32 | - ARM_HWCAP2_A64_SME_F16F32 | - ARM_HWCAP2_A64_SME_I8I32)); - GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64); - GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64); - GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64); - GET_FEATURE_ID(aa64_hbc, ARM_HWCAP2_A64_HBC); - GET_FEATURE_ID(aa64_mops, ARM_HWCAP2_A64_MOPS); - GET_FEATURE_ID(aa64_sve2p1, ARM_HWCAP2_A64_SVE2P1); - GET_FEATURE_ID(aa64_sme2, (ARM_HWCAP2_A64_SME2 | - ARM_HWCAP2_A64_SME_I16I32 | - ARM_HWCAP2_A64_SME_BI32I32)); - GET_FEATURE_ID(aa64_sme2p1, ARM_HWCAP2_A64_SME2P1); - GET_FEATURE_ID(aa64_sme_b16b16, ARM_HWCAP2_A64_SME_B16B16); - GET_FEATURE_ID(aa64_sme_f16f16, ARM_HWCAP2_A64_SME_F16F16); - GET_FEATURE_ID(aa64_sve_b16b16, ARM_HWCAP2_A64_SVE_B16B16); - - return hwcaps; -} - -const char *elf_hwcap_str(uint32_t bit) -{ - static const char * const hwcap_str[] = { - [__builtin_ctz(ARM_HWCAP_A64_FP )] = "fp", - [__builtin_ctz(ARM_HWCAP_A64_ASIMD )] = "asimd", - [__builtin_ctz(ARM_HWCAP_A64_EVTSTRM )] = "evtstrm", - [__builtin_ctz(ARM_HWCAP_A64_AES )] = "aes", - [__builtin_ctz(ARM_HWCAP_A64_PMULL )] = "pmull", - [__builtin_ctz(ARM_HWCAP_A64_SHA1 )] = "sha1", - [__builtin_ctz(ARM_HWCAP_A64_SHA2 )] = "sha2", - [__builtin_ctz(ARM_HWCAP_A64_CRC32 )] = "crc32", - [__builtin_ctz(ARM_HWCAP_A64_ATOMICS )] = "atomics", - [__builtin_ctz(ARM_HWCAP_A64_FPHP )] = "fphp", - [__builtin_ctz(ARM_HWCAP_A64_ASIMDHP )] = "asimdhp", - [__builtin_ctz(ARM_HWCAP_A64_CPUID )] = "cpuid", - [__builtin_ctz(ARM_HWCAP_A64_ASIMDRDM)] = "asimdrdm", - [__builtin_ctz(ARM_HWCAP_A64_JSCVT )] = "jscvt", - [__builtin_ctz(ARM_HWCAP_A64_FCMA )] = "fcma", - [__builtin_ctz(ARM_HWCAP_A64_LRCPC )] = "lrcpc", - [__builtin_ctz(ARM_HWCAP_A64_DCPOP )] = "dcpop", - [__builtin_ctz(ARM_HWCAP_A64_SHA3 )] = "sha3", - [__builtin_ctz(ARM_HWCAP_A64_SM3 )] = "sm3", - [__builtin_ctz(ARM_HWCAP_A64_SM4 )] = "sm4", - [__builtin_ctz(ARM_HWCAP_A64_ASIMDDP )] = "asimddp", - [__builtin_ctz(ARM_HWCAP_A64_SHA512 )] = "sha512", - [__builtin_ctz(ARM_HWCAP_A64_SVE )] = "sve", - [__builtin_ctz(ARM_HWCAP_A64_ASIMDFHM)] = "asimdfhm", - [__builtin_ctz(ARM_HWCAP_A64_DIT )] = "dit", - [__builtin_ctz(ARM_HWCAP_A64_USCAT )] = "uscat", - [__builtin_ctz(ARM_HWCAP_A64_ILRCPC )] = "ilrcpc", - [__builtin_ctz(ARM_HWCAP_A64_FLAGM )] = "flagm", - [__builtin_ctz(ARM_HWCAP_A64_SSBS )] = "ssbs", - [__builtin_ctz(ARM_HWCAP_A64_SB )] = "sb", - [__builtin_ctz(ARM_HWCAP_A64_PACA )] = "paca", - [__builtin_ctz(ARM_HWCAP_A64_PACG )] = "pacg", - [__builtin_ctzll(ARM_HWCAP_A64_GCS )] = "gcs", - [__builtin_ctzll(ARM_HWCAP_A64_CMPBR )] = "cmpbr", - [__builtin_ctzll(ARM_HWCAP_A64_FPRCVT)] = "fprcvt", - [__builtin_ctzll(ARM_HWCAP_A64_F8MM8 )] = "f8mm8", - [__builtin_ctzll(ARM_HWCAP_A64_F8MM4 )] = "f8mm4", - [__builtin_ctzll(ARM_HWCAP_A64_SVE_F16MM)] = "svef16mm", - [__builtin_ctzll(ARM_HWCAP_A64_SVE_ELTPERM)] = "sveeltperm", - [__builtin_ctzll(ARM_HWCAP_A64_SVE_AES2)] = "sveaes2", - [__builtin_ctzll(ARM_HWCAP_A64_SVE_BFSCALE)] = "svebfscale", - [__builtin_ctzll(ARM_HWCAP_A64_SVE2P2)] = "sve2p2", - [__builtin_ctzll(ARM_HWCAP_A64_SME2P2)] = "sme2p2", - [__builtin_ctzll(ARM_HWCAP_A64_SME_SBITPERM)] = "smesbitperm", - [__builtin_ctzll(ARM_HWCAP_A64_SME_AES)] = "smeaes", - [__builtin_ctzll(ARM_HWCAP_A64_SME_SFEXPA)] = "smesfexpa", - [__builtin_ctzll(ARM_HWCAP_A64_SME_STMOP)] = "smestmop", - [__builtin_ctzll(ARM_HWCAP_A64_SME_SMOP4)] = "smesmop4", - }; - - return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; -} - -const char *elf_hwcap2_str(uint32_t bit) -{ - static const char * const hwcap_str[] = { - [__builtin_ctz(ARM_HWCAP2_A64_DCPODP )] = "dcpodp", - [__builtin_ctz(ARM_HWCAP2_A64_SVE2 )] = "sve2", - [__builtin_ctz(ARM_HWCAP2_A64_SVEAES )] = "sveaes", - [__builtin_ctz(ARM_HWCAP2_A64_SVEPMULL )] = "svepmull", - [__builtin_ctz(ARM_HWCAP2_A64_SVEBITPERM )] = "svebitperm", - [__builtin_ctz(ARM_HWCAP2_A64_SVESHA3 )] = "svesha3", - [__builtin_ctz(ARM_HWCAP2_A64_SVESM4 )] = "svesm4", - [__builtin_ctz(ARM_HWCAP2_A64_FLAGM2 )] = "flagm2", - [__builtin_ctz(ARM_HWCAP2_A64_FRINT )] = "frint", - [__builtin_ctz(ARM_HWCAP2_A64_SVEI8MM )] = "svei8mm", - [__builtin_ctz(ARM_HWCAP2_A64_SVEF32MM )] = "svef32mm", - [__builtin_ctz(ARM_HWCAP2_A64_SVEF64MM )] = "svef64mm", - [__builtin_ctz(ARM_HWCAP2_A64_SVEBF16 )] = "svebf16", - [__builtin_ctz(ARM_HWCAP2_A64_I8MM )] = "i8mm", - [__builtin_ctz(ARM_HWCAP2_A64_BF16 )] = "bf16", - [__builtin_ctz(ARM_HWCAP2_A64_DGH )] = "dgh", - [__builtin_ctz(ARM_HWCAP2_A64_RNG )] = "rng", - [__builtin_ctz(ARM_HWCAP2_A64_BTI )] = "bti", - [__builtin_ctz(ARM_HWCAP2_A64_MTE )] = "mte", - [__builtin_ctz(ARM_HWCAP2_A64_ECV )] = "ecv", - [__builtin_ctz(ARM_HWCAP2_A64_AFP )] = "afp", - [__builtin_ctz(ARM_HWCAP2_A64_RPRES )] = "rpres", - [__builtin_ctz(ARM_HWCAP2_A64_MTE3 )] = "mte3", - [__builtin_ctz(ARM_HWCAP2_A64_SME )] = "sme", - [__builtin_ctz(ARM_HWCAP2_A64_SME_I16I64 )] = "smei16i64", - [__builtin_ctz(ARM_HWCAP2_A64_SME_F64F64 )] = "smef64f64", - [__builtin_ctz(ARM_HWCAP2_A64_SME_I8I32 )] = "smei8i32", - [__builtin_ctz(ARM_HWCAP2_A64_SME_F16F32 )] = "smef16f32", - [__builtin_ctz(ARM_HWCAP2_A64_SME_B16F32 )] = "smeb16f32", - [__builtin_ctz(ARM_HWCAP2_A64_SME_F32F32 )] = "smef32f32", - [__builtin_ctz(ARM_HWCAP2_A64_SME_FA64 )] = "smefa64", - [__builtin_ctz(ARM_HWCAP2_A64_WFXT )] = "wfxt", - [__builtin_ctzll(ARM_HWCAP2_A64_EBF16 )] = "ebf16", - [__builtin_ctzll(ARM_HWCAP2_A64_SVE_EBF16 )] = "sveebf16", - [__builtin_ctzll(ARM_HWCAP2_A64_CSSC )] = "cssc", - [__builtin_ctzll(ARM_HWCAP2_A64_RPRFM )] = "rprfm", - [__builtin_ctzll(ARM_HWCAP2_A64_SVE2P1 )] = "sve2p1", - [__builtin_ctzll(ARM_HWCAP2_A64_SME2 )] = "sme2", - [__builtin_ctzll(ARM_HWCAP2_A64_SME2P1 )] = "sme2p1", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_I16I32 )] = "smei16i32", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_BI32I32)] = "smebi32i32", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_B16B16 )] = "smeb16b16", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_F16F16 )] = "smef16f16", - [__builtin_ctzll(ARM_HWCAP2_A64_MOPS )] = "mops", - [__builtin_ctzll(ARM_HWCAP2_A64_HBC )] = "hbc", - [__builtin_ctzll(ARM_HWCAP2_A64_SVE_B16B16 )] = "sveb16b16", - [__builtin_ctzll(ARM_HWCAP2_A64_LRCPC3 )] = "lrcpc3", - [__builtin_ctzll(ARM_HWCAP2_A64_LSE128 )] = "lse128", - [__builtin_ctzll(ARM_HWCAP2_A64_FPMR )] = "fpmr", - [__builtin_ctzll(ARM_HWCAP2_A64_LUT )] = "lut", - [__builtin_ctzll(ARM_HWCAP2_A64_FAMINMAX )] = "faminmax", - [__builtin_ctzll(ARM_HWCAP2_A64_F8CVT )] = "f8cvt", - [__builtin_ctzll(ARM_HWCAP2_A64_F8FMA )] = "f8fma", - [__builtin_ctzll(ARM_HWCAP2_A64_F8DP4 )] = "f8dp4", - [__builtin_ctzll(ARM_HWCAP2_A64_F8DP2 )] = "f8dp2", - [__builtin_ctzll(ARM_HWCAP2_A64_F8E4M3 )] = "f8e4m3", - [__builtin_ctzll(ARM_HWCAP2_A64_F8E5M2 )] = "f8e5m2", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_LUTV2 )] = "smelutv2", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_F8F16 )] = "smef8f16", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_F8F32 )] = "smef8f32", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_SF8DP4 )] = "smesf8dp4", - [__builtin_ctzll(ARM_HWCAP2_A64_SME_SF8DP2 )] = "smesf8dp2", - [__builtin_ctzll(ARM_HWCAP2_A64_POE )] = "poe", - }; - - return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; -} - -#undef GET_FEATURE_ID - -#if TARGET_BIG_ENDIAN -# define VDSO_HEADER "vdso-be.c.inc" -#else -# define VDSO_HEADER "vdso-le.c.inc" -#endif - -#endif /* not TARGET_AARCH64 */ - -#endif /* TARGET_ARM */ - -#ifdef TARGET_SPARC - -#ifndef TARGET_SPARC64 -# define ELF_CLASS ELFCLASS32 -# define ELF_ARCH EM_SPARC -#elif defined(TARGET_ABI32) -# define ELF_CLASS ELFCLASS32 -# define elf_check_arch(x) ((x) == EM_SPARC32PLUS || (x) == EM_SPARC) -#else -# define ELF_CLASS ELFCLASS64 -# define ELF_ARCH EM_SPARCV9 -#endif - -#include "elf.h" - -#define ELF_HWCAP get_elf_hwcap() - -static uint32_t get_elf_hwcap(void) -{ - /* There are not many sparc32 hwcap bits -- we have all of them. */ - uint32_t r = HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | - HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV; - -#ifdef TARGET_SPARC64 - CPUSPARCState *env = cpu_env(thread_cpu); - uint32_t features = env->def.features; - - r |= HWCAP_SPARC_V9 | HWCAP_SPARC_V8PLUS; - /* 32x32 multiply and divide are efficient. */ - r |= HWCAP_SPARC_MUL32 | HWCAP_SPARC_DIV32; - /* We don't have an internal feature bit for this. */ - r |= HWCAP_SPARC_POPC; - r |= features & CPU_FEATURE_FSMULD ? HWCAP_SPARC_FSMULD : 0; - r |= features & CPU_FEATURE_VIS1 ? HWCAP_SPARC_VIS : 0; - r |= features & CPU_FEATURE_VIS2 ? HWCAP_SPARC_VIS2 : 0; - r |= features & CPU_FEATURE_FMAF ? HWCAP_SPARC_FMAF : 0; - r |= features & CPU_FEATURE_VIS3 ? HWCAP_SPARC_VIS3 : 0; - r |= features & CPU_FEATURE_IMA ? HWCAP_SPARC_IMA : 0; -#endif - - return r; -} - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - /* Note that target_cpu_copy_regs does not read psr/tstate. */ - regs->pc = infop->entry; - regs->npc = regs->pc + 4; - regs->y = 0; - regs->u_regs[14] = (infop->start_stack - 16 * sizeof(abi_ulong) - - TARGET_STACK_BIAS); -} -#endif /* TARGET_SPARC */ - -#ifdef TARGET_PPC - -#define ELF_MACHINE PPC_ELF_MACHINE - -#if defined(TARGET_PPC64) - -#define elf_check_arch(x) ( (x) == EM_PPC64 ) - -#define ELF_CLASS ELFCLASS64 - -#else - -#define ELF_CLASS ELFCLASS32 -#define EXSTACK_DEFAULT true - -#endif - -#define ELF_ARCH EM_PPC - -/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP). - See arch/powerpc/include/asm/cputable.h. */ -enum { - QEMU_PPC_FEATURE_32 = 0x80000000, - QEMU_PPC_FEATURE_64 = 0x40000000, - QEMU_PPC_FEATURE_601_INSTR = 0x20000000, - QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000, - QEMU_PPC_FEATURE_HAS_FPU = 0x08000000, - QEMU_PPC_FEATURE_HAS_MMU = 0x04000000, - QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000, - QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000, - QEMU_PPC_FEATURE_HAS_SPE = 0x00800000, - QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000, - QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000, - QEMU_PPC_FEATURE_NO_TB = 0x00100000, - QEMU_PPC_FEATURE_POWER4 = 0x00080000, - QEMU_PPC_FEATURE_POWER5 = 0x00040000, - QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000, - QEMU_PPC_FEATURE_CELL = 0x00010000, - QEMU_PPC_FEATURE_BOOKE = 0x00008000, - QEMU_PPC_FEATURE_SMT = 0x00004000, - QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000, - QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000, - QEMU_PPC_FEATURE_PA6T = 0x00000800, - QEMU_PPC_FEATURE_HAS_DFP = 0x00000400, - QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200, - QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100, - QEMU_PPC_FEATURE_HAS_VSX = 0x00000080, - QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040, - - QEMU_PPC_FEATURE_TRUE_LE = 0x00000002, - QEMU_PPC_FEATURE_PPC_LE = 0x00000001, - - /* Feature definitions in AT_HWCAP2. */ - QEMU_PPC_FEATURE2_ARCH_2_07 = 0x80000000, /* ISA 2.07 */ - QEMU_PPC_FEATURE2_HAS_HTM = 0x40000000, /* Hardware Transactional Memory */ - QEMU_PPC_FEATURE2_HAS_DSCR = 0x20000000, /* Data Stream Control Register */ - QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */ - QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */ - QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */ - QEMU_PPC_FEATURE2_VEC_CRYPTO = 0x02000000, - QEMU_PPC_FEATURE2_HTM_NOSC = 0x01000000, - QEMU_PPC_FEATURE2_ARCH_3_00 = 0x00800000, /* ISA 3.00 */ - QEMU_PPC_FEATURE2_HAS_IEEE128 = 0x00400000, /* VSX IEEE Bin Float 128-bit */ - QEMU_PPC_FEATURE2_DARN = 0x00200000, /* darn random number insn */ - QEMU_PPC_FEATURE2_SCV = 0x00100000, /* scv syscall */ - QEMU_PPC_FEATURE2_HTM_NO_SUSPEND = 0x00080000, /* TM w/o suspended state */ - QEMU_PPC_FEATURE2_ARCH_3_1 = 0x00040000, /* ISA 3.1 */ - QEMU_PPC_FEATURE2_MMA = 0x00020000, /* Matrix-Multiply Assist */ -}; - -#define ELF_HWCAP get_elf_hwcap() - -static uint32_t get_elf_hwcap(void) -{ - PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); - uint32_t features = 0; - - /* We don't have to be terribly complete here; the high points are - Altivec/FP/SPE support. Anything else is just a bonus. */ -#define GET_FEATURE(flag, feature) \ - do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) -#define GET_FEATURE2(flags, feature) \ - do { \ - if ((cpu->env.insns_flags2 & flags) == flags) { \ - features |= feature; \ - } \ - } while (0) - GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64); - GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU); - GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC); - GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE); - GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE); - GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE); - GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE); - GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC); - GET_FEATURE2(PPC2_DFP, QEMU_PPC_FEATURE_HAS_DFP); - GET_FEATURE2(PPC2_VSX, QEMU_PPC_FEATURE_HAS_VSX); - GET_FEATURE2((PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | - PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206), - QEMU_PPC_FEATURE_ARCH_2_06); -#undef GET_FEATURE -#undef GET_FEATURE2 - - return features; -} - -#define ELF_HWCAP2 get_elf_hwcap2() - -static uint32_t get_elf_hwcap2(void) -{ - PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); - uint32_t features = 0; - -#define GET_FEATURE(flag, feature) \ - do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) -#define GET_FEATURE2(flag, feature) \ - do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0) - - GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL); - GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR); - GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | - PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07 | - QEMU_PPC_FEATURE2_VEC_CRYPTO); - GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00 | - QEMU_PPC_FEATURE2_DARN | QEMU_PPC_FEATURE2_HAS_IEEE128); - GET_FEATURE2(PPC2_ISA310, QEMU_PPC_FEATURE2_ARCH_3_1 | - QEMU_PPC_FEATURE2_MMA); - -#undef GET_FEATURE -#undef GET_FEATURE2 - - return features; -} - -/* - * The requirements here are: - * - keep the final alignment of sp (sp & 0xf) - * - make sure the 32-bit value at the first 16 byte aligned position of - * AUXV is greater than 16 for glibc compatibility. - * AT_IGNOREPPC is used for that. - * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, - * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. - */ -#define DLINFO_ARCH_ITEMS 5 -#define ARCH_DLINFO \ - do { \ - PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); \ - /* \ - * Handle glibc compatibility: these magic entries must \ - * be at the lowest addresses in the final auxv. \ - */ \ - NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ - NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ - NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \ - NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \ - NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ - } while (0) - -static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) -{ - _regs->gpr[1] = infop->start_stack; -#if defined(TARGET_PPC64) - if (get_ppc64_abi(infop) < 2) { - uint64_t val; - get_user_u64(val, infop->entry + 8); - _regs->gpr[2] = val + infop->load_bias; - get_user_u64(val, infop->entry); - infop->entry = val + infop->load_bias; - } else { - _regs->gpr[12] = infop->entry; /* r12 set to global entry address */ - } -#endif - _regs->nip = infop->entry; -} - -/* See linux kernel: arch/powerpc/include/asm/elf.h. */ -#define ELF_NREG 48 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env) -{ - int i; - target_ulong ccr = 0; - - for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { - (*regs)[i] = tswapreg(env->gpr[i]); - } - - (*regs)[32] = tswapreg(env->nip); - (*regs)[33] = tswapreg(env->msr); - (*regs)[35] = tswapreg(env->ctr); - (*regs)[36] = tswapreg(env->lr); - (*regs)[37] = tswapreg(cpu_read_xer(env)); - - ccr = ppc_get_cr(env); - (*regs)[38] = tswapreg(ccr); -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -#ifndef TARGET_PPC64 -# define VDSO_HEADER "vdso-32.c.inc" -#elif TARGET_BIG_ENDIAN -# define VDSO_HEADER "vdso-64.c.inc" -#else -# define VDSO_HEADER "vdso-64le.c.inc" -#endif - -#endif - -#ifdef TARGET_LOONGARCH64 - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_LOONGARCH -#define EXSTACK_DEFAULT true - -#define elf_check_arch(x) ((x) == EM_LOONGARCH) - -#define VDSO_HEADER "vdso.c.inc" - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - /*Set crmd PG,DA = 1,0 */ - regs->csr.crmd = 2 << 3; - regs->csr.era = infop->entry; - regs->regs[3] = infop->start_stack; -} - -/* See linux kernel: arch/loongarch/include/asm/elf.h */ -#define ELF_NREG 45 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -enum { - TARGET_EF_R0 = 0, - TARGET_EF_CSR_ERA = TARGET_EF_R0 + 33, - TARGET_EF_CSR_BADV = TARGET_EF_R0 + 34, -}; - -static void elf_core_copy_regs(target_elf_gregset_t *regs, - const CPULoongArchState *env) -{ - int i; - - (*regs)[TARGET_EF_R0] = 0; - - for (i = 1; i < ARRAY_SIZE(env->gpr); i++) { - (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]); - } - - (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc); - (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->CSR_BADV); -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -#define ELF_HWCAP get_elf_hwcap() - -/* See arch/loongarch/include/uapi/asm/hwcap.h */ -enum { - HWCAP_LOONGARCH_CPUCFG = (1 << 0), - HWCAP_LOONGARCH_LAM = (1 << 1), - HWCAP_LOONGARCH_UAL = (1 << 2), - HWCAP_LOONGARCH_FPU = (1 << 3), - HWCAP_LOONGARCH_LSX = (1 << 4), - HWCAP_LOONGARCH_LASX = (1 << 5), - HWCAP_LOONGARCH_CRC32 = (1 << 6), - HWCAP_LOONGARCH_COMPLEX = (1 << 7), - HWCAP_LOONGARCH_CRYPTO = (1 << 8), - HWCAP_LOONGARCH_LVZ = (1 << 9), - HWCAP_LOONGARCH_LBT_X86 = (1 << 10), - HWCAP_LOONGARCH_LBT_ARM = (1 << 11), - HWCAP_LOONGARCH_LBT_MIPS = (1 << 12), -}; - -static uint32_t get_elf_hwcap(void) -{ - LoongArchCPU *cpu = LOONGARCH_CPU(thread_cpu); - uint32_t hwcaps = 0; - - hwcaps |= HWCAP_LOONGARCH_CRC32; - - if (FIELD_EX32(cpu->env.cpucfg[1], CPUCFG1, UAL)) { - hwcaps |= HWCAP_LOONGARCH_UAL; - } - - if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, FP)) { - hwcaps |= HWCAP_LOONGARCH_FPU; - } - - if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LAM)) { - hwcaps |= HWCAP_LOONGARCH_LAM; - } - - if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) { - hwcaps |= HWCAP_LOONGARCH_LSX; - } - - if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) { - hwcaps |= HWCAP_LOONGARCH_LASX; - } - - return hwcaps; -} - -#define ELF_PLATFORM "loongarch" - -#endif /* TARGET_LOONGARCH64 */ - -#ifdef TARGET_MIPS - -#ifdef TARGET_MIPS64 -#define ELF_CLASS ELFCLASS64 -#else -#define ELF_CLASS ELFCLASS32 -#endif -#define ELF_ARCH EM_MIPS -#define EXSTACK_DEFAULT true - -#ifdef TARGET_ABI_MIPSN32 -#define elf_check_abi(x) ((x) & EF_MIPS_ABI2) -#else -#define elf_check_abi(x) (!((x) & EF_MIPS_ABI2)) -#endif - -#define ELF_BASE_PLATFORM get_elf_base_platform() - -#define MATCH_PLATFORM_INSN(_flags, _base_platform) \ - do { if ((cpu->env.insn_flags & (_flags)) == _flags) \ - { return _base_platform; } } while (0) - -static const char *get_elf_base_platform(void) -{ - MIPSCPU *cpu = MIPS_CPU(thread_cpu); - - /* 64 bit ISAs goes first */ - MATCH_PLATFORM_INSN(CPU_MIPS64R6, "mips64r6"); - MATCH_PLATFORM_INSN(CPU_MIPS64R5, "mips64r5"); - MATCH_PLATFORM_INSN(CPU_MIPS64R2, "mips64r2"); - MATCH_PLATFORM_INSN(CPU_MIPS64R1, "mips64"); - MATCH_PLATFORM_INSN(CPU_MIPS5, "mips5"); - MATCH_PLATFORM_INSN(CPU_MIPS4, "mips4"); - MATCH_PLATFORM_INSN(CPU_MIPS3, "mips3"); - - /* 32 bit ISAs */ - MATCH_PLATFORM_INSN(CPU_MIPS32R6, "mips32r6"); - MATCH_PLATFORM_INSN(CPU_MIPS32R5, "mips32r5"); - MATCH_PLATFORM_INSN(CPU_MIPS32R2, "mips32r2"); - MATCH_PLATFORM_INSN(CPU_MIPS32R1, "mips32"); - MATCH_PLATFORM_INSN(CPU_MIPS2, "mips2"); - - /* Fallback */ - return "mips"; -} -#undef MATCH_PLATFORM_INSN - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->cp0_status = 2 << CP0St_KSU; - regs->cp0_epc = infop->entry; - regs->regs[29] = infop->start_stack; -} - -/* See linux kernel: arch/mips/include/asm/elf.h. */ -#define ELF_NREG 45 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -/* See linux kernel: arch/mips/include/asm/reg.h. */ -enum { -#ifdef TARGET_MIPS64 - TARGET_EF_R0 = 0, -#else - TARGET_EF_R0 = 6, -#endif - TARGET_EF_R26 = TARGET_EF_R0 + 26, - TARGET_EF_R27 = TARGET_EF_R0 + 27, - TARGET_EF_LO = TARGET_EF_R0 + 32, - TARGET_EF_HI = TARGET_EF_R0 + 33, - TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34, - TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35, - TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36, - TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37 -}; - -/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ -static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env) -{ - int i; - - for (i = 0; i < TARGET_EF_R0; i++) { - (*regs)[i] = 0; - } - (*regs)[TARGET_EF_R0] = 0; - - for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { - (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]); - } - - (*regs)[TARGET_EF_R26] = 0; - (*regs)[TARGET_EF_R27] = 0; - (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]); - (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]); - (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC); - (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr); - (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status); - (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause); -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -/* See arch/mips/include/uapi/asm/hwcap.h. */ -enum { - HWCAP_MIPS_R6 = (1 << 0), - HWCAP_MIPS_MSA = (1 << 1), - HWCAP_MIPS_CRC32 = (1 << 2), - HWCAP_MIPS_MIPS16 = (1 << 3), - HWCAP_MIPS_MDMX = (1 << 4), - HWCAP_MIPS_MIPS3D = (1 << 5), - HWCAP_MIPS_SMARTMIPS = (1 << 6), - HWCAP_MIPS_DSP = (1 << 7), - HWCAP_MIPS_DSP2 = (1 << 8), - HWCAP_MIPS_DSP3 = (1 << 9), - HWCAP_MIPS_MIPS16E2 = (1 << 10), - HWCAP_LOONGSON_MMI = (1 << 11), - HWCAP_LOONGSON_EXT = (1 << 12), - HWCAP_LOONGSON_EXT2 = (1 << 13), - HWCAP_LOONGSON_CPUCFG = (1 << 14), -}; - -#define ELF_HWCAP get_elf_hwcap() - -#define GET_FEATURE_INSN(_flag, _hwcap) \ - do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0) - -#define GET_FEATURE_REG_SET(_reg, _mask, _hwcap) \ - do { if (cpu->env._reg & (_mask)) { hwcaps |= _hwcap; } } while (0) - -#define GET_FEATURE_REG_EQU(_reg, _start, _length, _val, _hwcap) \ - do { \ - if (extract32(cpu->env._reg, (_start), (_length)) == (_val)) { \ - hwcaps |= _hwcap; \ - } \ - } while (0) - -static uint32_t get_elf_hwcap(void) -{ - MIPSCPU *cpu = MIPS_CPU(thread_cpu); - uint32_t hwcaps = 0; - - GET_FEATURE_REG_EQU(CP0_Config0, CP0C0_AR, CP0C0_AR_LENGTH, - 2, HWCAP_MIPS_R6); - GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA); - GET_FEATURE_INSN(ASE_LMMI, HWCAP_LOONGSON_MMI); - GET_FEATURE_INSN(ASE_LEXT, HWCAP_LOONGSON_EXT); - - return hwcaps; -} - -#undef GET_FEATURE_REG_EQU -#undef GET_FEATURE_REG_SET -#undef GET_FEATURE_INSN - -#endif /* TARGET_MIPS */ - -#ifdef TARGET_MICROBLAZE - -#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_MICROBLAZE - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->pc = infop->entry; - regs->r1 = infop->start_stack; - -} - -#define ELF_EXEC_PAGESIZE 4096 - -#define USE_ELF_CORE_DUMP -#define ELF_NREG 38 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ -static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env) -{ - int i, pos = 0; - - for (i = 0; i < 32; i++) { - (*regs)[pos++] = tswapreg(env->regs[i]); - } - - (*regs)[pos++] = tswapreg(env->pc); - (*regs)[pos++] = tswapreg(mb_cpu_read_msr(env)); - (*regs)[pos++] = 0; - (*regs)[pos++] = tswapreg(env->ear); - (*regs)[pos++] = 0; - (*regs)[pos++] = tswapreg(env->esr); -} - -#endif /* TARGET_MICROBLAZE */ - -#ifdef TARGET_OPENRISC - -#define ELF_ARCH EM_OPENRISC -#define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2MSB - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->pc = infop->entry; - regs->gpr[1] = infop->start_stack; -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 8192 - -/* See linux kernel arch/openrisc/include/asm/elf.h. */ -#define ELF_NREG 34 /* gprs and pc, sr */ -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -static void elf_core_copy_regs(target_elf_gregset_t *regs, - const CPUOpenRISCState *env) -{ - int i; - - for (i = 0; i < 32; i++) { - (*regs)[i] = tswapreg(cpu_get_gpr(env, i)); - } - (*regs)[32] = tswapreg(env->pc); - (*regs)[33] = tswapreg(cpu_get_sr(env)); -} -#define ELF_HWCAP 0 -#define ELF_PLATFORM NULL - -#endif /* TARGET_OPENRISC */ - -#ifdef TARGET_SH4 - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_SH - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - /* Check other registers XXXXX */ - regs->pc = infop->entry; - regs->regs[15] = infop->start_stack; -} - -/* See linux kernel: arch/sh/include/asm/elf.h. */ -#define ELF_NREG 23 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -/* See linux kernel: arch/sh/include/asm/ptrace.h. */ -enum { - TARGET_REG_PC = 16, - TARGET_REG_PR = 17, - TARGET_REG_SR = 18, - TARGET_REG_GBR = 19, - TARGET_REG_MACH = 20, - TARGET_REG_MACL = 21, - TARGET_REG_SYSCALL = 22 -}; - -static inline void elf_core_copy_regs(target_elf_gregset_t *regs, - const CPUSH4State *env) -{ - int i; - - for (i = 0; i < 16; i++) { - (*regs)[i] = tswapreg(env->gregs[i]); - } - - (*regs)[TARGET_REG_PC] = tswapreg(env->pc); - (*regs)[TARGET_REG_PR] = tswapreg(env->pr); - (*regs)[TARGET_REG_SR] = tswapreg(env->sr); - (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr); - (*regs)[TARGET_REG_MACH] = tswapreg(env->mach); - (*regs)[TARGET_REG_MACL] = tswapreg(env->macl); - (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */ -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -enum { - SH_CPU_HAS_FPU = 0x0001, /* Hardware FPU support */ - SH_CPU_HAS_P2_FLUSH_BUG = 0x0002, /* Need to flush the cache in P2 area */ - SH_CPU_HAS_MMU_PAGE_ASSOC = 0x0004, /* SH3: TLB way selection bit support */ - SH_CPU_HAS_DSP = 0x0008, /* SH-DSP: DSP support */ - SH_CPU_HAS_PERF_COUNTER = 0x0010, /* Hardware performance counters */ - SH_CPU_HAS_PTEA = 0x0020, /* PTEA register */ - SH_CPU_HAS_LLSC = 0x0040, /* movli.l/movco.l */ - SH_CPU_HAS_L2_CACHE = 0x0080, /* Secondary cache / URAM */ - SH_CPU_HAS_OP32 = 0x0100, /* 32-bit instruction support */ - SH_CPU_HAS_PTEAEX = 0x0200, /* PTE ASID Extension support */ -}; - -#define ELF_HWCAP get_elf_hwcap() - -static uint32_t get_elf_hwcap(void) -{ - SuperHCPU *cpu = SUPERH_CPU(thread_cpu); - uint32_t hwcap = 0; - - hwcap |= SH_CPU_HAS_FPU; - - if (cpu->env.features & SH_FEATURE_SH4A) { - hwcap |= SH_CPU_HAS_LLSC; - } - - return hwcap; -} - -#endif - -#ifdef TARGET_M68K - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_68K - -/* ??? Does this need to do anything? - #define ELF_PLAT_INIT(_r) */ - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->usp = infop->start_stack; - regs->sr = 0; - regs->pc = infop->entry; -} - -/* See linux kernel: arch/m68k/include/asm/elf.h. */ -#define ELF_NREG 20 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env) -{ - (*regs)[0] = tswapreg(env->dregs[1]); - (*regs)[1] = tswapreg(env->dregs[2]); - (*regs)[2] = tswapreg(env->dregs[3]); - (*regs)[3] = tswapreg(env->dregs[4]); - (*regs)[4] = tswapreg(env->dregs[5]); - (*regs)[5] = tswapreg(env->dregs[6]); - (*regs)[6] = tswapreg(env->dregs[7]); - (*regs)[7] = tswapreg(env->aregs[0]); - (*regs)[8] = tswapreg(env->aregs[1]); - (*regs)[9] = tswapreg(env->aregs[2]); - (*regs)[10] = tswapreg(env->aregs[3]); - (*regs)[11] = tswapreg(env->aregs[4]); - (*regs)[12] = tswapreg(env->aregs[5]); - (*regs)[13] = tswapreg(env->aregs[6]); - (*regs)[14] = tswapreg(env->dregs[0]); - (*regs)[15] = tswapreg(env->aregs[7]); - (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */ - (*regs)[17] = tswapreg(env->sr); - (*regs)[18] = tswapreg(env->pc); - (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */ -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 8192 - -#endif - -#ifdef TARGET_ALPHA - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_ALPHA - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->pc = infop->entry; - regs->ps = 8; - regs->usp = infop->start_stack; -} - -#define ELF_EXEC_PAGESIZE 8192 - -#endif /* TARGET_ALPHA */ - -#ifdef TARGET_S390X - -#define ELF_CLASS ELFCLASS64 -#define ELF_DATA ELFDATA2MSB -#define ELF_ARCH EM_S390 - -#include "elf.h" - -#define ELF_HWCAP get_elf_hwcap() - -#define GET_FEATURE(_feat, _hwcap) \ - do { if (s390_has_feat(_feat)) { hwcap |= _hwcap; } } while (0) - -uint32_t get_elf_hwcap(void) -{ - /* - * Let's assume we always have esan3 and zarch. - * 31-bit processes can use 64-bit registers (high gprs). - */ - uint32_t hwcap = HWCAP_S390_ESAN3 | HWCAP_S390_ZARCH | HWCAP_S390_HIGH_GPRS; - - GET_FEATURE(S390_FEAT_STFLE, HWCAP_S390_STFLE); - GET_FEATURE(S390_FEAT_MSA, HWCAP_S390_MSA); - GET_FEATURE(S390_FEAT_LONG_DISPLACEMENT, HWCAP_S390_LDISP); - GET_FEATURE(S390_FEAT_EXTENDED_IMMEDIATE, HWCAP_S390_EIMM); - if (s390_has_feat(S390_FEAT_EXTENDED_TRANSLATION_3) && - s390_has_feat(S390_FEAT_ETF3_ENH)) { - hwcap |= HWCAP_S390_ETF3EH; - } - GET_FEATURE(S390_FEAT_VECTOR, HWCAP_S390_VXRS); - GET_FEATURE(S390_FEAT_VECTOR_ENH, HWCAP_S390_VXRS_EXT); - GET_FEATURE(S390_FEAT_VECTOR_ENH2, HWCAP_S390_VXRS_EXT2); - - return hwcap; -} - -const char *elf_hwcap_str(uint32_t bit) -{ - static const char *hwcap_str[] = { - [HWCAP_S390_NR_ESAN3] = "esan3", - [HWCAP_S390_NR_ZARCH] = "zarch", - [HWCAP_S390_NR_STFLE] = "stfle", - [HWCAP_S390_NR_MSA] = "msa", - [HWCAP_S390_NR_LDISP] = "ldisp", - [HWCAP_S390_NR_EIMM] = "eimm", - [HWCAP_S390_NR_DFP] = "dfp", - [HWCAP_S390_NR_HPAGE] = "edat", - [HWCAP_S390_NR_ETF3EH] = "etf3eh", - [HWCAP_S390_NR_HIGH_GPRS] = "highgprs", - [HWCAP_S390_NR_TE] = "te", - [HWCAP_S390_NR_VXRS] = "vx", - [HWCAP_S390_NR_VXRS_BCD] = "vxd", - [HWCAP_S390_NR_VXRS_EXT] = "vxe", - [HWCAP_S390_NR_GS] = "gs", - [HWCAP_S390_NR_VXRS_EXT2] = "vxe2", - [HWCAP_S390_NR_VXRS_PDE] = "vxp", - [HWCAP_S390_NR_SORT] = "sort", - [HWCAP_S390_NR_DFLT] = "dflt", - [HWCAP_S390_NR_NNPA] = "nnpa", - [HWCAP_S390_NR_PCI_MIO] = "pcimio", - [HWCAP_S390_NR_SIE] = "sie", - }; - - return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; -} - -static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) -{ - regs->psw.addr = infop->entry; - regs->psw.mask = PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | \ - PSW_MASK_MCHECK | PSW_MASK_PSTATE | PSW_MASK_64 | \ - PSW_MASK_32; - regs->gprs[15] = infop->start_stack; -} - -/* See linux kernel: arch/s390/include/uapi/asm/ptrace.h (s390_regs). */ -#define ELF_NREG 27 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -enum { - TARGET_REG_PSWM = 0, - TARGET_REG_PSWA = 1, - TARGET_REG_GPRS = 2, - TARGET_REG_ARS = 18, - TARGET_REG_ORIG_R2 = 26, -}; - -static void elf_core_copy_regs(target_elf_gregset_t *regs, - const CPUS390XState *env) -{ - int i; - uint32_t *aregs; - - (*regs)[TARGET_REG_PSWM] = tswapreg(env->psw.mask); - (*regs)[TARGET_REG_PSWA] = tswapreg(env->psw.addr); - for (i = 0; i < 16; i++) { - (*regs)[TARGET_REG_GPRS + i] = tswapreg(env->regs[i]); - } - aregs = (uint32_t *)&((*regs)[TARGET_REG_ARS]); - for (i = 0; i < 16; i++) { - aregs[i] = tswap32(env->aregs[i]); - } - (*regs)[TARGET_REG_ORIG_R2] = 0; -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -#define VDSO_HEADER "vdso.c.inc" - -#endif /* TARGET_S390X */ - -#ifdef TARGET_RISCV - -#define ELF_ARCH EM_RISCV - -#ifdef TARGET_RISCV32 -#define ELF_CLASS ELFCLASS32 -#define VDSO_HEADER "vdso-32.c.inc" -#else -#define ELF_CLASS ELFCLASS64 -#define VDSO_HEADER "vdso-64.c.inc" -#endif - -#define ELF_HWCAP get_elf_hwcap() - -static uint32_t get_elf_hwcap(void) -{ -#define MISA_BIT(EXT) (1 << (EXT - 'A')) - RISCVCPU *cpu = RISCV_CPU(thread_cpu); - uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A') - | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C') - | MISA_BIT('V'); - - return cpu->env.misa_ext & mask; -#undef MISA_BIT -} - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->sepc = infop->entry; - regs->sp = infop->start_stack; -} - -#define ELF_EXEC_PAGESIZE 4096 - -#endif /* TARGET_RISCV */ - -#ifdef TARGET_HPPA - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_PARISC -#define ELF_PLATFORM "PARISC" -#define STACK_GROWS_DOWN 0 -#define STACK_ALIGNMENT 64 - -#define VDSO_HEADER "vdso.c.inc" - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->iaoq[0] = infop->entry | PRIV_USER; - regs->iaoq[1] = regs->iaoq[0] + 4; - regs->gr[23] = 0; - regs->gr[24] = infop->argv; - regs->gr[25] = infop->argc; - /* The top-of-stack contains a linkage buffer. */ - regs->gr[30] = infop->start_stack + 64; - regs->gr[31] = infop->entry; -} - -#define LO_COMMPAGE 0 - -static bool init_guest_commpage(void) -{ - /* If reserved_va, then we have already mapped 0 page on the host. */ - if (!reserved_va) { - void *want, *addr; - - want = g2h_untagged(LO_COMMPAGE); - addr = mmap(want, TARGET_PAGE_SIZE, PROT_NONE, - MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0); - if (addr == MAP_FAILED) { - perror("Allocating guest commpage"); - exit(EXIT_FAILURE); - } - if (addr != want) { - return false; - } - } - - /* - * On Linux, page zero is normally marked execute only + gateway. - * Normal read or write is supposed to fail (thus PROT_NONE above), - * but specific offsets have kernel code mapped to raise permissions - * and implement syscalls. Here, simply mark the page executable. - * Special case the entry points during translation (see do_page_zero). - */ - page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK, - PAGE_EXEC | PAGE_VALID); - return true; -} - -#endif /* TARGET_HPPA */ - -#ifdef TARGET_XTENSA - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_XTENSA - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->windowbase = 0; - regs->windowstart = 1; - regs->areg[1] = infop->start_stack; - regs->pc = infop->entry; - if (info_is_fdpic(infop)) { - regs->areg[4] = infop->loadmap_addr; - regs->areg[5] = infop->interpreter_loadmap_addr; - if (infop->interpreter_loadmap_addr) { - regs->areg[6] = infop->interpreter_pt_dynamic_addr; - } else { - regs->areg[6] = infop->pt_dynamic_addr; - } - } -} - -/* See linux kernel: arch/xtensa/include/asm/elf.h. */ -#define ELF_NREG 128 -typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; - -enum { - TARGET_REG_PC, - TARGET_REG_PS, - TARGET_REG_LBEG, - TARGET_REG_LEND, - TARGET_REG_LCOUNT, - TARGET_REG_SAR, - TARGET_REG_WINDOWSTART, - TARGET_REG_WINDOWBASE, - TARGET_REG_THREADPTR, - TARGET_REG_AR0 = 64, -}; - -static void elf_core_copy_regs(target_elf_gregset_t *regs, - const CPUXtensaState *env) -{ - unsigned i; - - (*regs)[TARGET_REG_PC] = tswapreg(env->pc); - (*regs)[TARGET_REG_PS] = tswapreg(env->sregs[PS] & ~PS_EXCM); - (*regs)[TARGET_REG_LBEG] = tswapreg(env->sregs[LBEG]); - (*regs)[TARGET_REG_LEND] = tswapreg(env->sregs[LEND]); - (*regs)[TARGET_REG_LCOUNT] = tswapreg(env->sregs[LCOUNT]); - (*regs)[TARGET_REG_SAR] = tswapreg(env->sregs[SAR]); - (*regs)[TARGET_REG_WINDOWSTART] = tswapreg(env->sregs[WINDOW_START]); - (*regs)[TARGET_REG_WINDOWBASE] = tswapreg(env->sregs[WINDOW_BASE]); - (*regs)[TARGET_REG_THREADPTR] = tswapreg(env->uregs[THREADPTR]); - xtensa_sync_phys_from_window((CPUXtensaState *)env); - for (i = 0; i < env->config->nareg; ++i) { - (*regs)[TARGET_REG_AR0 + i] = tswapreg(env->phys_regs[i]); - } -} - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -#endif /* TARGET_XTENSA */ - -#ifdef TARGET_HEXAGON - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_HEXAGON - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ - regs->sepc = infop->entry; - regs->sp = infop->start_stack; -} - -#endif /* TARGET_HEXAGON */ - -#ifndef ELF_BASE_PLATFORM -#define ELF_BASE_PLATFORM (NULL) -#endif - -#ifndef ELF_PLATFORM -#define ELF_PLATFORM (NULL) -#endif - -#ifndef ELF_MACHINE -#define ELF_MACHINE ELF_ARCH -#endif - -#ifndef elf_check_arch -#define elf_check_arch(x) ((x) == ELF_ARCH) +#ifndef elf_check_machine +#define elf_check_machine(x) ((x) == ELF_MACHINE) #endif #ifndef elf_check_abi #define elf_check_abi(x) (1) #endif -#ifndef ELF_HWCAP -#define ELF_HWCAP 0 -#endif - #ifndef STACK_GROWS_DOWN #define STACK_GROWS_DOWN 1 #endif @@ -2139,59 +147,36 @@ static inline void init_thread(struct target_pt_regs *regs, #define EXSTACK_DEFAULT false #endif -#include "elf.h" - -/* We must delay the following stanzas until after "elf.h". */ -#if defined(TARGET_AARCH64) - -static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz, - const uint32_t *data, - struct image_info *info, - Error **errp) -{ - if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { - if (pr_datasz != sizeof(uint32_t)) { - error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND"); - return false; - } - /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */ - info->note_flags = *data; - } - return true; -} -#define ARCH_USE_GNU_PROPERTY 1 - -#else +/* + * Provide fallback definitions that the target may omit. + * One way or another, we'll get a link error if the setting of + * HAVE_* doesn't match the implementation. + */ +#ifndef HAVE_ELF_HWCAP +abi_ulong get_elf_hwcap(CPUState *cs) { return 0; } +#endif +#ifndef HAVE_ELF_HWCAP2 +abi_ulong get_elf_hwcap2(CPUState *cs) { g_assert_not_reached(); } +#define HAVE_ELF_HWCAP2 0 +#endif +#ifndef HAVE_ELF_PLATFORM +const char *get_elf_platform(CPUState *cs) { return NULL; } +#endif +#ifndef HAVE_ELF_BASE_PLATFORM +const char *get_elf_base_platform(CPUState *cs) { return NULL; } +#endif -static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz, - const uint32_t *data, - struct image_info *info, - Error **errp) +#ifndef HAVE_ELF_GNU_PROPERTY +bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz, + const uint32_t *data, struct image_info *info, + Error **errp) { g_assert_not_reached(); } -#define ARCH_USE_GNU_PROPERTY 0 - +#define HAVE_ELF_GNU_PROPERTY 0 #endif -struct exec -{ - unsigned int a_info; /* Use macros N_MAGIC, etc for access */ - unsigned int a_text; /* length of text, in bytes */ - unsigned int a_data; /* length of data, in bytes */ - unsigned int a_bss; /* length of uninitialized data area, in bytes */ - unsigned int a_syms; /* length of symbol table data in file, in bytes */ - unsigned int a_entry; /* start address */ - unsigned int a_trsize; /* length of relocation info for text, in bytes */ - unsigned int a_drsize; /* length of relocation info for data, in bytes */ -}; - - -#define N_MAGIC(exec) ((exec).a_info & 0xffff) -#define OMAGIC 0407 -#define NMAGIC 0410 -#define ZMAGIC 0413 -#define QMAGIC 0314 +#include "elf.h" #define DLINFO_ITEMS 16 @@ -2286,9 +271,9 @@ static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) } #endif -#ifdef USE_ELF_CORE_DUMP +#ifdef HAVE_ELF_CORE_DUMP static int elf_core_dump(int, const CPUArchState *); -#endif /* USE_ELF_CORE_DUMP */ +#endif /* HAVE_ELF_CORE_DUMP */ static void load_symbols(struct elfhdr *hdr, const ImageSource *src, abi_ulong load_bias); @@ -2309,7 +294,7 @@ static bool elf_check_ident(struct elfhdr *ehdr) This has to wait until after bswapping the header. */ static bool elf_check_ehdr(struct elfhdr *ehdr) { - return (elf_check_arch(ehdr->e_machine) + return (elf_check_machine(ehdr->e_machine) && elf_check_abi(ehdr->e_flags) && ehdr->e_ehsize == sizeof(struct elfhdr) && ehdr->e_phentsize == sizeof(struct elf_phdr) @@ -2592,7 +577,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, } u_base_platform = 0; - k_base_platform = ELF_BASE_PLATFORM; + k_base_platform = get_elf_base_platform(thread_cpu); if (k_base_platform) { size_t len = strlen(k_base_platform) + 1; if (STACK_GROWS_DOWN) { @@ -2608,7 +593,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, } u_platform = 0; - k_platform = ELF_PLATFORM; + k_platform = get_elf_platform(thread_cpu); if (k_platform) { size_t len = strlen(k_platform) + 1; if (STACK_GROWS_DOWN) { @@ -2660,9 +645,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, #ifdef DLINFO_ARCH_ITEMS size += DLINFO_ARCH_ITEMS * 2; #endif -#ifdef ELF_HWCAP2 - size += 2; -#endif + if (HAVE_ELF_HWCAP2) { + size += 2; + } info->auxv_len = size * n; size += envc + argc + 2; @@ -2716,16 +701,15 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); - NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); + NEW_AUX_ENT(AT_HWCAP, get_elf_hwcap(thread_cpu)); NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes); NEW_AUX_ENT(AT_SECURE, (abi_ulong) qemu_getauxval(AT_SECURE)); NEW_AUX_ENT(AT_EXECFN, info->file_string); -#ifdef ELF_HWCAP2 - NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2); -#endif - + if (HAVE_ELF_HWCAP2) { + NEW_AUX_ENT(AT_HWCAP2, get_elf_hwcap(thread_cpu)); + } if (u_base_platform) { NEW_AUX_ENT(AT_BASE_PLATFORM, u_base_platform); } @@ -2771,8 +755,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, #else #define HI_COMMPAGE 0 #define LO_COMMPAGE -1 -#ifndef INIT_GUEST_COMMPAGE -#define init_guest_commpage() true +#ifndef HAVE_GUEST_COMMPAGE +bool init_guest_commpage(void) { return true; } #endif #endif @@ -3207,7 +1191,7 @@ static bool parse_elf_properties(const ImageSource *src, uint32_t prev_type; /* Unless the arch requires properties, ignore them. */ - if (!ARCH_USE_GNU_PROPERTY) { + if (!HAVE_ELF_GNU_PROPERTY) { return true; } @@ -3630,14 +1614,17 @@ static void load_elf_interp(const char *filename, struct image_info *info, load_elf_image(filename, &src, info, &ehdr, NULL); } -#ifndef vdso_image_info +#ifndef HAVE_VDSO_IMAGE_INFO +const VdsoImageInfo *get_vdso_image_info(uint32_t elf_flags) +{ #ifdef VDSO_HEADER #include VDSO_HEADER -#define vdso_image_info(flags) &vdso_image_info + return &vdso_image_info; #else -#define vdso_image_info(flags) NULL -#endif /* VDSO_HEADER */ -#endif /* vdso_image_info */ + return NULL; +#endif +} +#endif /* HAVE_VDSO_IMAGE_INFO */ static void load_elf_vdso(struct image_info *info, const VdsoImageInfo *vdso) { @@ -3968,7 +1955,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) * Load a vdso if available, which will amongst other things contain the * signal trampolines. Otherwise, allocate a separate page for them. */ - const VdsoImageInfo *vdso = vdso_image_info(info->elf_flags); + const VdsoImageInfo *vdso = get_vdso_image_info(info->elf_flags); if (vdso) { load_elf_vdso(&vdso_info, vdso); info->vdso = vdso_info.load_bias; @@ -3999,14 +1986,14 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) g_free(elf_interpreter); } -#ifdef USE_ELF_CORE_DUMP +#ifdef HAVE_ELF_CORE_DUMP bprm->core_dump = &elf_core_dump; #endif return 0; } -#ifdef USE_ELF_CORE_DUMP +#ifdef HAVE_ELF_CORE_DUMP /* * Definitions to generate Intel SVR4-like core files. @@ -4022,23 +2009,18 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) * Core dump code is copied from linux kernel (fs/binfmt_elf.c). * * Porting ELF coredump for target is (quite) simple process. First you - * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for + * define HAVE_ELF_CORE_DUMP in target ELF code (where init_thread() for * the target resides): * - * #define USE_ELF_CORE_DUMP + * #define HAVE_ELF_CORE_DUMP * - * Next you define type of register set used for dumping. ELF specification - * says that it needs to be array of elf_greg_t that has size of ELF_NREG. - * - * typedef <target_regtype> target_elf_greg_t; - * #define ELF_NREG <number of registers> - * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG]; + * Next you define type of register set used for dumping: + * typedef struct target_elf_gregset_t { ... } target_elf_gregset_t; * * Last step is to implement target specific function that copies registers * from given cpu into just specified register set. Prototype is: * - * static void elf_core_copy_regs(taret_elf_gregset_t *regs, - * const CPUArchState *env); + * void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUArchState *env); * * Parameters: * regs - copy register values into here (allocated and zeroed by caller) @@ -4382,7 +2364,7 @@ static int wmr_fill_region_phdr(void *opaque, vaddr start, phdr->p_flags = (flags & PAGE_READ ? PF_R : 0) | (flags & PAGE_WRITE_ORG ? PF_W : 0) | (flags & PAGE_EXEC ? PF_X : 0); - phdr->p_align = ELF_EXEC_PAGESIZE; + phdr->p_align = TARGET_PAGE_SIZE; bswap_phdr(phdr, 1); d->phdr = phdr + 1; @@ -4490,7 +2472,7 @@ static int elf_core_dump(int signr, const CPUArchState *env) offset += size_note("CORE", sizeof(struct target_elf_prpsinfo)); offset += size_note("CORE", sizeof(struct target_elf_prstatus)) * cpus; note_size = offset - note_offset; - data_offset = ROUND_UP(offset, ELF_EXEC_PAGESIZE); + data_offset = TARGET_PAGE_ALIGN(offset); /* Do not dump if the corefile size exceeds the limit. */ if (dumpsize.rlim_cur != RLIM_INFINITY @@ -4569,9 +2551,4 @@ static int elf_core_dump(int signr, const CPUArchState *env) } return ret; } -#endif /* USE_ELF_CORE_DUMP */ - -void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) -{ - init_thread(regs, infop); -} +#endif /* HAVE_ELF_CORE_DUMP */ |