1From fa9bcabe2387bb230ef82d62827ad6f93b8a1e61 Mon Sep 17 00:00:00 2001 2From: Frederic Konrad <fkonrad@amd.com> 3Date: Wed, 17 Jan 2024 18:15:06 +0000 4Subject: [PATCH 1/2] linux-user/*: workaround for missing MAP_FIXED_NOREPLACE 5 6QEMU v8.1.0 recently requires MAP_FIXED_NOREPLACE flags implementation for mmap. 7 8This is missing from ubuntu 18.04, thus this patch catches the mmap calls which 9could use that new flag and forwards them to mmap when MAP_FIXED_NOREPLACE 10flag isn't set or emulates them by checking the returned address w.r.t the 11requested address. 12 13Signed-off-by: Frederic Konrad <fkonrad@amd.com> 14Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com> 15 16Upstream-Status: Inappropriate [OE specific] 17 18The upstream only supports the last two major releases of an OS. The ones 19they have declared all have kernel 4.17 or newer. 20 21See: 22https://xilinx.slack.com/archives/D04G2647CTV/p1705074697942019 23 24https://www.qemu.org/docs/master/about/build-platforms.html 25 26 The project aims to support the most recent major version at all times for up 27 to five years after its initial release. Support for the previous major 28 version will be dropped 2 years after the new major version is released or 29 when the vendor itself drops support, whichever comes first. 30 31Signed-off-by: Mark Hatle <mark.hatle@amd.com> 32--- 33 linux-user/elfload.c | 7 +++-- 34 linux-user/meson.build | 1 + 35 linux-user/mmap-fixed.c | 63 +++++++++++++++++++++++++++++++++++++++++ 36 linux-user/mmap-fixed.h | 39 +++++++++++++++++++++++++ 37 linux-user/mmap.c | 31 +++++++++++--------- 38 linux-user/syscall.c | 1 + 39 6 files changed, 125 insertions(+), 17 deletions(-) 40 create mode 100644 linux-user/mmap-fixed.c 41 create mode 100644 linux-user/mmap-fixed.h 42 43Index: qemu-8.2.1/linux-user/elfload.c 44=================================================================== 45--- qemu-8.2.1.orig/linux-user/elfload.c 46+++ qemu-8.2.1/linux-user/elfload.c 47@@ -22,6 +22,7 @@ 48 #include "qemu/error-report.h" 49 #include "target_signal.h" 50 #include "accel/tcg/debuginfo.h" 51+#include "mmap-fixed.h" 52 53 #ifdef TARGET_ARM 54 #include "target/arm/cpu-features.h" 55@@ -2765,9 +2766,9 @@ static abi_ulong create_elf_tables(abi_u 56 static int pgb_try_mmap(uintptr_t addr, uintptr_t addr_last, bool keep) 57 { 58 size_t size = addr_last - addr + 1; 59- void *p = mmap((void *)addr, size, PROT_NONE, 60- MAP_ANONYMOUS | MAP_PRIVATE | 61- MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); 62+ void *p = mmap_fixed_noreplace((void *)addr, size, PROT_NONE, 63+ MAP_ANONYMOUS | MAP_PRIVATE | 64+ MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); 65 int ret; 66 67 if (p == MAP_FAILED) { 68Index: qemu-8.2.1/linux-user/meson.build 69=================================================================== 70--- qemu-8.2.1.orig/linux-user/meson.build 71+++ qemu-8.2.1/linux-user/meson.build 72@@ -14,6 +14,7 @@ linux_user_ss.add(files( 73 'linuxload.c', 74 'main.c', 75 'mmap.c', 76+ 'mmap-fixed.c', 77 'signal.c', 78 'strace.c', 79 'syscall.c', 80Index: qemu-8.2.1/linux-user/mmap-fixed.c 81=================================================================== 82--- /dev/null 83+++ qemu-8.2.1/linux-user/mmap-fixed.c 84@@ -0,0 +1,63 @@ 85+/* 86+ * Workaround for MAP_FIXED_NOREPLACE 87+ * 88+ * Copyright (c) 2024, Advanced Micro Devices, Inc. 89+ * Developed by Fred Konrad <fkonrad@amd.com> 90+ * 91+ * Permission is hereby granted, free of charge, to any person obtaining a copy 92+ * of this software and associated documentation files (the "Software"), to deal 93+ * in the Software without restriction, including without limitation the rights 94+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 95+ * copies of the Software, and to permit persons to whom the Software is 96+ * furnished to do so, subject to the following conditions: 97+ * 98+ * The above copyright notice and this permission notice shall be included in 99+ * all copies or substantial portions of the Software. 100+ * 101+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 102+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 103+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 104+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 105+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 106+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 107+ * THE SOFTWARE. 108+ */ 109+ 110+#include <sys/mman.h> 111+#include <errno.h> 112+ 113+#ifndef MAP_FIXED_NOREPLACE 114+#include "mmap-fixed.h" 115+ 116+void *mmap_fixed_noreplace(void *addr, size_t len, int prot, int flags, 117+ int fd, off_t offset) 118+{ 119+ void *retaddr; 120+ 121+ if (!(flags & MAP_FIXED_NOREPLACE)) { 122+ /* General case, use the regular mmap. */ 123+ return mmap(addr, len, prot, flags, fd, offset); 124+ } 125+ 126+ /* Since MAP_FIXED_NOREPLACE is not implemented, try to emulate it. */ 127+ flags = flags & ~(MAP_FIXED_NOREPLACE | MAP_FIXED); 128+ retaddr = mmap(addr, len, prot, flags, fd, offset); 129+ if ((retaddr == addr) || (retaddr == MAP_FAILED)) { 130+ /* 131+ * Either the map worked and we get the good address so it can be 132+ * returned, or it failed and would have failed the same with 133+ * MAP_FIXED*, in which case return MAP_FAILED. 134+ */ 135+ return retaddr; 136+ } else { 137+ /* 138+ * Page has been mapped but not at the requested address.. unmap it and 139+ * return EEXIST. 140+ */ 141+ munmap(retaddr, len); 142+ errno = EEXIST; 143+ return MAP_FAILED; 144+ } 145+} 146+ 147+#endif 148Index: qemu-8.2.1/linux-user/mmap-fixed.h 149=================================================================== 150--- /dev/null 151+++ qemu-8.2.1/linux-user/mmap-fixed.h 152@@ -0,0 +1,39 @@ 153+/* 154+ * Workaround for MAP_FIXED_NOREPLACE 155+ * 156+ * Copyright (c) 2024, Advanced Micro Devices, Inc. 157+ * Developed by Fred Konrad <fkonrad@amd.com> 158+ * 159+ * Permission is hereby granted, free of charge, to any person obtaining a copy 160+ * of this software and associated documentation files (the "Software"), to deal 161+ * in the Software without restriction, including without limitation the rights 162+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 163+ * copies of the Software, and to permit persons to whom the Software is 164+ * furnished to do so, subject to the following conditions: 165+ * 166+ * The above copyright notice and this permission notice shall be included in 167+ * all copies or substantial portions of the Software. 168+ * 169+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 170+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 171+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 172+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 173+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 174+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 175+ * THE SOFTWARE. 176+ */ 177+ 178+#ifndef MMAP_FIXED_H 179+#define MMAP_FIXED_H 180+ 181+#ifndef MAP_FIXED_NOREPLACE 182+#define MAP_FIXED_NOREPLACE 0x100000 183+ 184+void *mmap_fixed_noreplace(void *addr, size_t len, int prot, int flags, 185+ int fd, off_t offset); 186+ 187+#else /* MAP_FIXED_NOREPLACE */ 188+#define mmap_fixed_noreplace mmap 189+#endif /* MAP_FIXED_NOREPLACE */ 190+ 191+#endif /* MMAP_FIXED_H */ 192Index: qemu-8.2.1/linux-user/mmap.c 193=================================================================== 194--- qemu-8.2.1.orig/linux-user/mmap.c 195+++ qemu-8.2.1/linux-user/mmap.c 196@@ -25,6 +25,7 @@ 197 #include "user-mmap.h" 198 #include "target_mman.h" 199 #include "qemu/interval-tree.h" 200+#include "mmap-fixed.h" 201 202 #ifdef TARGET_ARM 203 #include "target/arm/cpu-features.h" 204@@ -273,7 +274,7 @@ int target_mprotect(abi_ulong start, abi 205 static int do_munmap(void *addr, size_t len) 206 { 207 if (reserved_va) { 208- void *ptr = mmap(addr, len, PROT_NONE, 209+ void *ptr = mmap_fixed_noreplace(addr, len, PROT_NONE, 210 MAP_FIXED | MAP_ANONYMOUS 211 | MAP_PRIVATE | MAP_NORESERVE, -1, 0); 212 return ptr == addr ? 0 : -1; 213@@ -319,9 +320,9 @@ static bool mmap_frag(abi_ulong real_sta 214 * outside of the fragment we need to map. Allocate a new host 215 * page to cover, discarding whatever else may have been present. 216 */ 217- void *p = mmap(host_start, qemu_host_page_size, 218- target_to_host_prot(prot), 219- flags | MAP_ANONYMOUS, -1, 0); 220+ void *p = mmap_fixed_noreplace(host_start, qemu_host_page_size, 221+ target_to_host_prot(prot), 222+ flags | MAP_ANONYMOUS, -1, 0); 223 if (p != host_start) { 224 if (p != MAP_FAILED) { 225 munmap(p, qemu_host_page_size); 226@@ -420,8 +421,9 @@ abi_ulong mmap_find_vma(abi_ulong start, 227 * - mremap() with MREMAP_FIXED flag 228 * - shmat() with SHM_REMAP flag 229 */ 230- ptr = mmap(g2h_untagged(addr), size, PROT_NONE, 231- MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0); 232+ ptr = mmap_fixed_noreplace(g2h_untagged(addr), size, PROT_NONE, 233+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, 234+ -1, 0); 235 236 /* ENOMEM, if host address space has no memory */ 237 if (ptr == MAP_FAILED) { 238@@ -615,16 +617,16 @@ abi_long target_mmap(abi_ulong start, ab 239 * especially important if qemu_host_page_size > 240 * qemu_real_host_page_size. 241 */ 242- p = mmap(g2h_untagged(start), host_len, host_prot, 243- flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); 244+ p = mmap_fixed_noreplace(g2h_untagged(start), host_len, host_prot, 245+ flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); 246 if (p == MAP_FAILED) { 247 goto fail; 248 } 249 /* update start so that it points to the file position at 'offset' */ 250 host_start = (uintptr_t)p; 251 if (!(flags & MAP_ANONYMOUS)) { 252- p = mmap(g2h_untagged(start), len, host_prot, 253- flags | MAP_FIXED, fd, host_offset); 254+ p = mmap_fixed_noreplace(g2h_untagged(start), len, host_prot, 255+ flags | MAP_FIXED, fd, host_offset); 256 if (p == MAP_FAILED) { 257 munmap(g2h_untagged(start), host_len); 258 goto fail; 259@@ -749,8 +751,9 @@ abi_long target_mmap(abi_ulong start, ab 260 len1 = real_last - real_start + 1; 261 want_p = g2h_untagged(real_start); 262 263- p = mmap(want_p, len1, target_to_host_prot(target_prot), 264- flags, fd, offset1); 265+ p = mmap_fixed_noreplace(want_p, len1, 266+ target_to_host_prot(target_prot), 267+ flags, fd, offset1); 268 if (p != want_p) { 269 if (p != MAP_FAILED) { 270 munmap(p, len1); 271Index: qemu-8.2.1/linux-user/syscall.c 272=================================================================== 273--- qemu-8.2.1.orig/linux-user/syscall.c 274+++ qemu-8.2.1/linux-user/syscall.c 275@@ -145,6 +145,7 @@ 276 #include "qapi/error.h" 277 #include "fd-trans.h" 278 #include "cpu_loop-common.h" 279+#include "mmap-fixed.h" 280 281 #ifndef CLONE_IO 282 #define CLONE_IO 0x80000000 /* Clone io context */ 283