diff options
Diffstat (limited to 'linux-user/arm')
| -rw-r--r-- | linux-user/arm/elfload.c | 76 | ||||
| -rw-r--r-- | linux-user/arm/target_elf.h | 18 | ||||
| -rw-r--r-- | linux-user/arm/target_ptrace.h | 16 | ||||
| -rw-r--r-- | linux-user/arm/target_syscall.h | 8 |
4 files changed, 110 insertions, 8 deletions
diff --git a/linux-user/arm/elfload.c b/linux-user/arm/elfload.c index 7de1f13f4b..308ed23fcb 100644 --- a/linux-user/arm/elfload.c +++ b/linux-user/arm/elfload.c @@ -3,7 +3,11 @@ #include "qemu/osdep.h" #include "qemu.h" #include "loader.h" +#include "user-internals.h" +#include "target_elf.h" #include "target/arm/cpu-features.h" +#include "target_elf.h" +#include "elf.h" const char *get_elf_cpu_model(uint32_t eflags) @@ -199,3 +203,75 @@ const char *get_elf_platform(CPUState *cs) #undef END } + +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; +} + +void elf_core_copy_regs(target_elf_gregset_t *r, const CPUARMState *env) +{ + for (int i = 0; i < 16; ++i) { + r->pt.regs[i] = tswapal(env->regs[i]); + } + r->pt.cpsr = tswapal(cpsr_read((CPUARMState *)env)); + r->pt.orig_r0 = tswapal(env->regs[0]); /* FIXME */ +} + +#if TARGET_BIG_ENDIAN +# include "vdso-be8.c.inc" +# include "vdso-be32.c.inc" +#else +# include "vdso-le.c.inc" +#endif + +const VdsoImageInfo *get_vdso_image_info(uint32_t elf_flags) +{ +#if TARGET_BIG_ENDIAN + return (EF_ARM_EABI_VERSION(elf_flags) >= EF_ARM_EABI_VER4 + && (elf_flags & EF_ARM_BE8) + ? &vdso_be8_image_info + : &vdso_be32_image_info); +#else + return &vdso_image_info; +#endif +} diff --git a/linux-user/arm/target_elf.h b/linux-user/arm/target_elf.h index 856ca41b16..12cdc8e5a7 100644 --- a/linux-user/arm/target_elf.h +++ b/linux-user/arm/target_elf.h @@ -8,8 +8,26 @@ #ifndef ARM_TARGET_ELF_H #define ARM_TARGET_ELF_H +#include "target_ptrace.h" + +#define ELF_MACHINE EM_ARM +#define ELF_CLASS ELFCLASS32 +#define EXSTACK_DEFAULT true + #define HAVE_ELF_HWCAP 1 #define HAVE_ELF_HWCAP2 1 #define HAVE_ELF_PLATFORM 1 +#define HAVE_ELF_CORE_DUMP 1 +#define HAVE_VDSO_IMAGE_INFO 1 + +#define HI_COMMPAGE ((intptr_t)0xffff0f00u) + +/* + * See linux kernel: arch/arm/include/asm/elf.h, where + * elf_gregset_t is mapped to struct pt_regs via sizeof. + */ +typedef struct target_elf_gregset_t { + struct target_pt_regs pt; +} target_elf_gregset_t; #endif diff --git a/linux-user/arm/target_ptrace.h b/linux-user/arm/target_ptrace.h new file mode 100644 index 0000000000..1610b8e03c --- /dev/null +++ b/linux-user/arm/target_ptrace.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef ARM_TARGET_PTRACE_H +#define ARM_TARGET_PTRACE_H + +/* + * See arch/arm/include/uapi/asm/ptrace.h. + * Instead of an array and ARM_xx defines, use proper fields. + */ +struct target_pt_regs { + abi_ulong regs[16]; + abi_ulong cpsr; + abi_ulong orig_r0; +}; + +#endif /* ARM_TARGET_PTRACE_H */ diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h index 412ad434cf..8c4ddba717 100644 --- a/linux-user/arm/target_syscall.h +++ b/linux-user/arm/target_syscall.h @@ -1,14 +1,6 @@ #ifndef ARM_TARGET_SYSCALL_H #define ARM_TARGET_SYSCALL_H -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -/* uregs[0..15] are r0 to r15; uregs[16] is CPSR; uregs[17] is ORIG_r0 */ -struct target_pt_regs { - abi_long uregs[18]; -}; - #define ARM_SYSCALL_BASE 0x900000 #define ARM_THUMB_SYSCALL 0 |