$NetBSD$

--- src/arch/netbsd/mapping/mapshm.c.orig	2017-11-02 06:34:44.096973963 +0000
+++ src/arch/netbsd/mapping/mapshm.c
@@ -0,0 +1,190 @@
+/*
+ * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team".
+ *
+ * for details see file COPYING in the DOSEMU distribution
+ */
+
+/*
+ * Purpose: memory mapping library, anon-SHM backend.
+ *
+ * Authors: Stas Sergeev, Bart Oldeman.
+ *
+ */
+
+#include "emu.h"
+#include <unistd.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include "dosemu_config.h"
+#include "mapping.h"
+
+/* ------------------------------------------------------------ */
+
+#define Q__printf(f,cap,a...) ({\
+  Q_printf(f,decode_mapping_cap(cap),##a); \
+})
+
+static void *alias_mapping_shm(int cap, void *target, size_t mapsize, int protect, void *source)
+{
+  int flags = MREMAP_MAYMOVE;
+  /* The trick is to set old_len = 0,
+   * this won't unmap at the old address, but with
+   * shared mem the 'nopage' vm_op will map in the right
+   * pages. We need however to take care not to map
+   * past the end of the shm area
+   */
+  if (target != (void *)-1)
+    flags |= MREMAP_FIXED;
+  else
+    target = NULL;
+  target = mremap(source, 0, mapsize, flags, target);
+  if (target == MAP_FAILED) return MAP_FAILED;
+
+  mprotect(target, mapsize, protect);
+  return target;
+}
+
+static int open_mapping_shm(int cap)
+{
+  static int first =1;
+
+  if (cap) Q_printf("MAPPING: open, cap=%s\n",
+				decode_mapping_cap(cap));
+
+  if (first) {
+    void *ptr1, *ptr2 = MAP_FAILED;
+    first = 0;
+
+    /* do a test alias mapping. kernel 2.6.1 doesn't support our mremap trick */
+    ptr1 = mmap(0, PAGE_SIZE, PROT_NONE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    if (ptr1 != MAP_FAILED) {
+      ptr2 = mremap(ptr1, 0, PAGE_SIZE, MREMAP_MAYMOVE);
+      munmap(ptr1, PAGE_SIZE);
+      if (ptr2 != MAP_FAILED)
+        munmap(ptr2, PAGE_SIZE);
+    }
+    if (ptr2 == MAP_FAILED) {
+      Q_printf("MAPPING: not using mapshm because alias mapping does not work\n");
+      if (!cap)return 0;
+      leavedos(2);
+    }
+  }
+
+  /*
+   * Now handle individual cases.
+   * Don't forget that each of the below code pieces should only
+   * be executed once !
+   */
+
+#if 0
+  if (cap & MAPPING_OTHER) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_EMS) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_DPMI) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_VIDEO) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_VGAEMU) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_HGC) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_HMA) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_SHARED) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_INIT_HWRAM) {
+    /* none for now */
+  }
+#endif
+#if 0
+  if (cap & MAPPING_INIT_LOWRAM) {
+    /* none for now */
+  }
+#endif
+
+  return 1;
+}
+
+static void close_mapping_shm(int cap)
+{
+  Q_printf("MAPPING: close, cap=%s\n", decode_mapping_cap(cap));
+}
+
+static void *alloc_mapping_shm(int cap, size_t mapsize)
+{
+  Q__printf("MAPPING: alloc, cap=%s, mapsize=%zx\n", cap, mapsize);
+  return mmap(0, mapsize, PROT_READ | PROT_WRITE,
+    MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+}
+
+static void free_mapping_shm(int cap, void *addr, size_t mapsize)
+/* NOTE: addr needs to be the same as what was supplied by alloc_mapping_shm */
+{
+  Q__printf("MAPPING: free, cap=%s, addr=%p, mapsize=%zx\n",
+	cap, addr, mapsize);
+  munmap(addr, mapsize);
+}
+
+static void *realloc_mapping_shm(int cap, void *addr, size_t oldsize, size_t newsize)
+{
+  void *ret;
+  Q__printf("MAPPING: realloc, cap=%s, addr=%p, oldsize=%zx, newsize=%zx\n",
+	cap, addr, oldsize, newsize);
+
+  if (newsize <= oldsize)
+    return mremap(addr, oldsize, newsize, MREMAP_MAYMOVE);
+
+  /* we can't expand shared anonymous memory using mremap
+     so we must allocate a new region and memcpy to it */
+  ret = alloc_mapping_shm(cap, newsize);
+  if (ret != MAP_FAILED) {
+    memcpy(ret, addr, oldsize);
+    free_mapping_shm(cap, addr, oldsize);
+  }
+  return ret;
+}
+
+static int munmap_mapping_shm(int cap, void *addr, size_t mapsize)
+{
+  Q__printf("MAPPING: unmap, cap=%s, addr=%p, size=%zx\n",
+	cap, addr, mapsize);
+  return munmap(addr, mapsize);
+}
+
+struct mappingdrivers mappingdriver_ashm = {
+  "mapashm",
+  "anonymous non-expandable shared memory mapping",
+  open_mapping_shm,
+  close_mapping_shm,
+  alloc_mapping_shm,
+  free_mapping_shm,
+  realloc_mapping_shm,
+  munmap_mapping_shm,
+  alias_mapping_shm,
+};
