summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch
blob: cc53b1eeddf6a3c32aa4ea15e04e5cfd3d984e5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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 */