| From fa9bcabe2387bb230ef82d62827ad6f93b8a1e61 Mon Sep 17 00:00:00 2001 |
| From: Frederic Konrad <fkonrad@amd.com> |
| Date: Wed, 17 Jan 2024 18:15:06 +0000 |
| Subject: [PATCH 1/2] linux-user/*: workaround for missing MAP_FIXED_NOREPLACE |
| |
| QEMU v8.1.0 recently requires MAP_FIXED_NOREPLACE flags implementation for mmap. |
| |
| This is missing from ubuntu 18.04, thus this patch catches the mmap calls which |
| could use that new flag and forwards them to mmap when MAP_FIXED_NOREPLACE |
| flag isn't set or emulates them by checking the returned address w.r.t the |
| requested address. |
| |
| Signed-off-by: Frederic Konrad <fkonrad@amd.com> |
| Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com> |
| |
| Upstream-Status: Inappropriate [OE specific] |
| |
| The upstream only supports the last two major releases of an OS. The ones |
| they have declared all have kernel 4.17 or newer. |
| |
| See: |
| https://xilinx.slack.com/archives/D04G2647CTV/p1705074697942019 |
| |
| https://www.qemu.org/docs/master/about/build-platforms.html |
| |
| The project aims to support the most recent major version at all times for up |
| to five years after its initial release. Support for the previous major |
| version will be dropped 2 years after the new major version is released or |
| when the vendor itself drops support, whichever comes first. |
| |
| Signed-off-by: Mark Hatle <mark.hatle@amd.com> |
| --- |
| linux-user/elfload.c | 7 +++-- |
| linux-user/meson.build | 1 + |
| linux-user/mmap-fixed.c | 63 +++++++++++++++++++++++++++++++++++++++++ |
| linux-user/mmap-fixed.h | 39 +++++++++++++++++++++++++ |
| linux-user/mmap.c | 31 +++++++++++--------- |
| linux-user/syscall.c | 1 + |
| 6 files changed, 125 insertions(+), 17 deletions(-) |
| create mode 100644 linux-user/mmap-fixed.c |
| create mode 100644 linux-user/mmap-fixed.h |
| |
| Index: qemu-8.2.1/linux-user/elfload.c |
| =================================================================== |
| --- qemu-8.2.1.orig/linux-user/elfload.c |
| +++ qemu-8.2.1/linux-user/elfload.c |
| @@ -22,6 +22,7 @@ |
| #include "qemu/error-report.h" |
| #include "target_signal.h" |
| #include "accel/tcg/debuginfo.h" |
| +#include "mmap-fixed.h" |
| |
| #ifdef TARGET_ARM |
| #include "target/arm/cpu-features.h" |
| @@ -2765,9 +2766,9 @@ static abi_ulong create_elf_tables(abi_u |
| static int pgb_try_mmap(uintptr_t addr, uintptr_t addr_last, bool keep) |
| { |
| size_t size = addr_last - addr + 1; |
| - void *p = mmap((void *)addr, size, PROT_NONE, |
| - MAP_ANONYMOUS | MAP_PRIVATE | |
| - MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); |
| + void *p = mmap_fixed_noreplace((void *)addr, size, PROT_NONE, |
| + MAP_ANONYMOUS | MAP_PRIVATE | |
| + MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); |
| int ret; |
| |
| if (p == MAP_FAILED) { |
| Index: qemu-8.2.1/linux-user/meson.build |
| =================================================================== |
| --- qemu-8.2.1.orig/linux-user/meson.build |
| +++ qemu-8.2.1/linux-user/meson.build |
| @@ -14,6 +14,7 @@ linux_user_ss.add(files( |
| 'linuxload.c', |
| 'main.c', |
| 'mmap.c', |
| + 'mmap-fixed.c', |
| 'signal.c', |
| 'strace.c', |
| 'syscall.c', |
| Index: qemu-8.2.1/linux-user/mmap-fixed.c |
| =================================================================== |
| --- /dev/null |
| +++ qemu-8.2.1/linux-user/mmap-fixed.c |
| @@ -0,0 +1,63 @@ |
| +/* |
| + * Workaround for MAP_FIXED_NOREPLACE |
| + * |
| + * Copyright (c) 2024, Advanced Micro Devices, Inc. |
| + * Developed by Fred Konrad <fkonrad@amd.com> |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#include <sys/mman.h> |
| +#include <errno.h> |
| + |
| +#ifndef MAP_FIXED_NOREPLACE |
| +#include "mmap-fixed.h" |
| + |
| +void *mmap_fixed_noreplace(void *addr, size_t len, int prot, int flags, |
| + int fd, off_t offset) |
| +{ |
| + void *retaddr; |
| + |
| + if (!(flags & MAP_FIXED_NOREPLACE)) { |
| + /* General case, use the regular mmap. */ |
| + return mmap(addr, len, prot, flags, fd, offset); |
| + } |
| + |
| + /* Since MAP_FIXED_NOREPLACE is not implemented, try to emulate it. */ |
| + flags = flags & ~(MAP_FIXED_NOREPLACE | MAP_FIXED); |
| + retaddr = mmap(addr, len, prot, flags, fd, offset); |
| + if ((retaddr == addr) || (retaddr == MAP_FAILED)) { |
| + /* |
| + * Either the map worked and we get the good address so it can be |
| + * returned, or it failed and would have failed the same with |
| + * MAP_FIXED*, in which case return MAP_FAILED. |
| + */ |
| + return retaddr; |
| + } else { |
| + /* |
| + * Page has been mapped but not at the requested address.. unmap it and |
| + * return EEXIST. |
| + */ |
| + munmap(retaddr, len); |
| + errno = EEXIST; |
| + return MAP_FAILED; |
| + } |
| +} |
| + |
| +#endif |
| Index: qemu-8.2.1/linux-user/mmap-fixed.h |
| =================================================================== |
| --- /dev/null |
| +++ qemu-8.2.1/linux-user/mmap-fixed.h |
| @@ -0,0 +1,39 @@ |
| +/* |
| + * Workaround for MAP_FIXED_NOREPLACE |
| + * |
| + * Copyright (c) 2024, Advanced Micro Devices, Inc. |
| + * Developed by Fred Konrad <fkonrad@amd.com> |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#ifndef MMAP_FIXED_H |
| +#define MMAP_FIXED_H |
| + |
| +#ifndef MAP_FIXED_NOREPLACE |
| +#define MAP_FIXED_NOREPLACE 0x100000 |
| + |
| +void *mmap_fixed_noreplace(void *addr, size_t len, int prot, int flags, |
| + int fd, off_t offset); |
| + |
| +#else /* MAP_FIXED_NOREPLACE */ |
| +#define mmap_fixed_noreplace mmap |
| +#endif /* MAP_FIXED_NOREPLACE */ |
| + |
| +#endif /* MMAP_FIXED_H */ |
| Index: qemu-8.2.1/linux-user/mmap.c |
| =================================================================== |
| --- qemu-8.2.1.orig/linux-user/mmap.c |
| +++ qemu-8.2.1/linux-user/mmap.c |
| @@ -25,6 +25,7 @@ |
| #include "user-mmap.h" |
| #include "target_mman.h" |
| #include "qemu/interval-tree.h" |
| +#include "mmap-fixed.h" |
| |
| #ifdef TARGET_ARM |
| #include "target/arm/cpu-features.h" |
| @@ -273,7 +274,7 @@ int target_mprotect(abi_ulong start, abi |
| static int do_munmap(void *addr, size_t len) |
| { |
| if (reserved_va) { |
| - void *ptr = mmap(addr, len, PROT_NONE, |
| + void *ptr = mmap_fixed_noreplace(addr, len, PROT_NONE, |
| MAP_FIXED | MAP_ANONYMOUS |
| | MAP_PRIVATE | MAP_NORESERVE, -1, 0); |
| return ptr == addr ? 0 : -1; |
| @@ -319,9 +320,9 @@ static bool mmap_frag(abi_ulong real_sta |
| * outside of the fragment we need to map. Allocate a new host |
| * page to cover, discarding whatever else may have been present. |
| */ |
| - void *p = mmap(host_start, qemu_host_page_size, |
| - target_to_host_prot(prot), |
| - flags | MAP_ANONYMOUS, -1, 0); |
| + void *p = mmap_fixed_noreplace(host_start, qemu_host_page_size, |
| + target_to_host_prot(prot), |
| + flags | MAP_ANONYMOUS, -1, 0); |
| if (p != host_start) { |
| if (p != MAP_FAILED) { |
| munmap(p, qemu_host_page_size); |
| @@ -420,8 +421,9 @@ abi_ulong mmap_find_vma(abi_ulong start, |
| * - mremap() with MREMAP_FIXED flag |
| * - shmat() with SHM_REMAP flag |
| */ |
| - ptr = mmap(g2h_untagged(addr), size, PROT_NONE, |
| - MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0); |
| + ptr = mmap_fixed_noreplace(g2h_untagged(addr), size, PROT_NONE, |
| + MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, |
| + -1, 0); |
| |
| /* ENOMEM, if host address space has no memory */ |
| if (ptr == MAP_FAILED) { |
| @@ -615,16 +617,16 @@ abi_long target_mmap(abi_ulong start, ab |
| * especially important if qemu_host_page_size > |
| * qemu_real_host_page_size. |
| */ |
| - p = mmap(g2h_untagged(start), host_len, host_prot, |
| - flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); |
| + p = mmap_fixed_noreplace(g2h_untagged(start), host_len, host_prot, |
| + flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); |
| if (p == MAP_FAILED) { |
| goto fail; |
| } |
| /* update start so that it points to the file position at 'offset' */ |
| host_start = (uintptr_t)p; |
| if (!(flags & MAP_ANONYMOUS)) { |
| - p = mmap(g2h_untagged(start), len, host_prot, |
| - flags | MAP_FIXED, fd, host_offset); |
| + p = mmap_fixed_noreplace(g2h_untagged(start), len, host_prot, |
| + flags | MAP_FIXED, fd, host_offset); |
| if (p == MAP_FAILED) { |
| munmap(g2h_untagged(start), host_len); |
| goto fail; |
| @@ -749,8 +751,9 @@ abi_long target_mmap(abi_ulong start, ab |
| len1 = real_last - real_start + 1; |
| want_p = g2h_untagged(real_start); |
| |
| - p = mmap(want_p, len1, target_to_host_prot(target_prot), |
| - flags, fd, offset1); |
| + p = mmap_fixed_noreplace(want_p, len1, |
| + target_to_host_prot(target_prot), |
| + flags, fd, offset1); |
| if (p != want_p) { |
| if (p != MAP_FAILED) { |
| munmap(p, len1); |
| Index: qemu-8.2.1/linux-user/syscall.c |
| =================================================================== |
| --- qemu-8.2.1.orig/linux-user/syscall.c |
| +++ qemu-8.2.1/linux-user/syscall.c |
| @@ -145,6 +145,7 @@ |
| #include "qapi/error.h" |
| #include "fd-trans.h" |
| #include "cpu_loop-common.h" |
| +#include "mmap-fixed.h" |
| |
| #ifndef CLONE_IO |
| #define CLONE_IO 0x80000000 /* Clone io context */ |