diff options
| author | Richard Henderson <richard.henderson@linaro.org> | 2025-07-29 09:11:12 -1000 |
|---|---|---|
| committer | Richard Henderson <richard.henderson@linaro.org> | 2025-08-30 07:04:04 +1000 |
| commit | a56ef5e8454e42c0d263a97a1297ae67f4ce19cd (patch) | |
| tree | e63579b2fa0772cb9d4bd9a6f2b93d5488de1ceb /linux-user/arm | |
| parent | 8d4a6f8e4c95e11a3da2e38682da2819d4e2160c (diff) | |
| download | focaccia-qemu-a56ef5e8454e42c0d263a97a1297ae67f4ce19cd.tar.gz focaccia-qemu-a56ef5e8454e42c0d263a97a1297ae67f4ce19cd.zip | |
linux-user: Move init_guest_commpage to arm/elfload.c
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user/arm')
| -rw-r--r-- | linux-user/arm/elfload.c | 46 | ||||
| -rw-r--r-- | linux-user/arm/target_elf.h | 2 |
2 files changed, 48 insertions, 0 deletions
diff --git a/linux-user/arm/elfload.c b/linux-user/arm/elfload.c index f811c2f07a..1205687976 100644 --- a/linux-user/arm/elfload.c +++ b/linux-user/arm/elfload.c @@ -3,6 +3,8 @@ #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" @@ -201,6 +203,50 @@ 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) { diff --git a/linux-user/arm/target_elf.h b/linux-user/arm/target_elf.h index fa8f8af2f3..5f81a43efb 100644 --- a/linux-user/arm/target_elf.h +++ b/linux-user/arm/target_elf.h @@ -15,6 +15,8 @@ #define HAVE_ELF_PLATFORM 1 #define HAVE_ELF_CORE_DUMP 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. |