pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

dosemu2: Add scratch of NetBSD porting files



Module Name:	pkgsrc-wip
Committed By:	Kamil Rytarowski <n54%gmx.com@localhost>
Pushed By:	kamil
Date:		Thu Nov 2 07:35:38 2017 +0100
Changeset:	93efb16689e7cc83a8d6bed68eaa25b2e86c2ff3

Modified Files:
	dosemu2/distinfo
Added Files:
	dosemu2/patches/patch-src_arch_netbsd_Makefile.main
	dosemu2/patches/patch-src_arch_netbsd_async_Makefile
	dosemu2/patches/patch-src_arch_netbsd_async_backtrace-symbols.c
	dosemu2/patches/patch-src_arch_netbsd_async_debug.c
	dosemu2/patches/patch-src_arch_netbsd_async_debug.h
	dosemu2/patches/patch-src_arch_netbsd_async_signal.c
	dosemu2/patches/patch-src_arch_netbsd_async_sigsegv.c
	dosemu2/patches/patch-src_arch_netbsd_mapping_Makefile
	dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.c
	dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.d
	dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.o
	dosemu2/patches/patch-src_arch_netbsd_mapping_mapping.c
	dosemu2/patches/patch-src_arch_netbsd_mapping_mapping.d
	dosemu2/patches/patch-src_arch_netbsd_mapping_mapshm.c
	dosemu2/patches/patch-src_arch_netbsd_mapping_mapshm.d
	dosemu2/patches/patch-src_arch_netbsd_mcontext_386-ucontext.h
	dosemu2/patches/patch-src_arch_netbsd_mcontext_COPYRIGHT
	dosemu2/patches/patch-src_arch_netbsd_mcontext_Makefile
	dosemu2/patches/patch-src_arch_netbsd_mcontext_amd64-ucontext.h
	dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.S
	dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.d
	dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.o
	dosemu2/patches/patch-src_arch_netbsd_mcontext_context.c
	dosemu2/patches/patch-src_arch_netbsd_mcontext_context.d
	dosemu2/patches/patch-src_arch_netbsd_mcontext_context.o
	dosemu2/patches/patch-src_arch_netbsd_mcontext_mcontext.h
	dosemu2/patches/patch-src_base_dev_misc_timers.c
	dosemu2/patches/patch-src_base_kbd__unicode_getfd.c
	dosemu2/patches/patch-src_base_kbd__unicode_keyb__raw.c
	dosemu2/patches/patch-src_base_kbd__unicode_keymaps.c
	dosemu2/patches/patch-src_base_misc_libpcl_Makefile
	dosemu2/patches/patch-src_include_debug.h

Log Message:
dosemu2: Add scratch of NetBSD porting files

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=93efb16689e7cc83a8d6bed68eaa25b2e86c2ff3

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 dosemu2/distinfo                                   |   32 +
 .../patches/patch-src_arch_netbsd_Makefile.main    |  286 +++++
 .../patches/patch-src_arch_netbsd_async_Makefile   |   18 +
 ...patch-src_arch_netbsd_async_backtrace-symbols.c |  333 ++++++
 .../patches/patch-src_arch_netbsd_async_debug.c    |  221 ++++
 .../patches/patch-src_arch_netbsd_async_debug.h    |   11 +
 .../patches/patch-src_arch_netbsd_async_signal.c   | 1215 ++++++++++++++++++++
 .../patches/patch-src_arch_netbsd_async_sigsegv.c  |  508 ++++++++
 .../patches/patch-src_arch_netbsd_mapping_Makefile |   35 +
 .../patch-src_arch_netbsd_mapping_mapfile.c        |  304 +++++
 .../patch-src_arch_netbsd_mapping_mapfile.d        |   18 +
 .../patch-src_arch_netbsd_mapping_mapfile.o        |    3 +
 .../patch-src_arch_netbsd_mapping_mapping.c        |  786 +++++++++++++
 .../patch-src_arch_netbsd_mapping_mapping.d        |   19 +
 .../patches/patch-src_arch_netbsd_mapping_mapshm.c |  195 ++++
 .../patches/patch-src_arch_netbsd_mapping_mapshm.d |   17 +
 .../patch-src_arch_netbsd_mcontext_386-ucontext.h  |   65 ++
 .../patch-src_arch_netbsd_mcontext_COPYRIGHT       |   48 +
 .../patch-src_arch_netbsd_mcontext_Makefile        |   14 +
 ...patch-src_arch_netbsd_mcontext_amd64-ucontext.h |   81 ++
 .../patches/patch-src_arch_netbsd_mcontext_asm.S   |  107 ++
 .../patches/patch-src_arch_netbsd_mcontext_asm.d   |    6 +
 .../patches/patch-src_arch_netbsd_mcontext_asm.o   |    3 +
 .../patch-src_arch_netbsd_mcontext_context.c       |   68 ++
 .../patch-src_arch_netbsd_mcontext_context.d       |    7 +
 .../patch-src_arch_netbsd_mcontext_context.o       |    3 +
 .../patch-src_arch_netbsd_mcontext_mcontext.h      |   58 +
 dosemu2/patches/patch-src_base_dev_misc_timers.c   |   14 +
 .../patches/patch-src_base_kbd__unicode_getfd.c    |   14 +
 .../patch-src_base_kbd__unicode_keyb__raw.c        |   14 +
 .../patches/patch-src_base_kbd__unicode_keymaps.c  |   15 +
 .../patches/patch-src_base_misc_libpcl_Makefile    |   14 +
 dosemu2/patches/patch-src_include_debug.h          |   13 +
 33 files changed, 4545 insertions(+)

diffs:
diff --git a/dosemu2/distinfo b/dosemu2/distinfo
index 59a5133180..868426a8bb 100644
--- a/dosemu2/distinfo
+++ b/dosemu2/distinfo
@@ -4,3 +4,35 @@ SHA1 (qemu-2.8.1.tar.bz2) = 224289c5e568e400920363820a0647e2aca569e7
 RMD160 (qemu-2.8.1.tar.bz2) = 93f71138d19c871195c9e0b1a7ba66275773f93a
 SHA512 (qemu-2.8.1.tar.bz2) = 0397b4029cdcb77ed053c44b3579a3f34894038e6fc6b4aa88de14515f5a78bf2f41c5e865f37111529f567c85d2f1c4deefae47dde54f76eac79410e5b2bdda
 Size (qemu-2.8.1.tar.bz2) = 28366270 bytes
+SHA1 (patch-src_arch_netbsd_Makefile.main) = cbcb051d93df3feb4f7d6d365295c24f58c4d1c9
+SHA1 (patch-src_arch_netbsd_async_Makefile) = f67f8e623ed6219f80a3524f96d42e3802b1fc26
+SHA1 (patch-src_arch_netbsd_async_backtrace-symbols.c) = 994ab7ed59d6fd6de4d0d5018cce99eaf0b29e95
+SHA1 (patch-src_arch_netbsd_async_debug.c) = a74eea8642178eb7feab4d89beff64529c75f675
+SHA1 (patch-src_arch_netbsd_async_debug.h) = 5b215af8775c9ae0257175cf0056c3f9de071929
+SHA1 (patch-src_arch_netbsd_async_signal.c) = 8099c106a2be65ec8275385b39e7e1dba86e6ca3
+SHA1 (patch-src_arch_netbsd_async_sigsegv.c) = 5deb0f2169960f07ea984fee86c0fa598d078af2
+SHA1 (patch-src_arch_netbsd_mapping_Makefile) = 96c551cb65483fee641f7e820e71564706a39c53
+SHA1 (patch-src_arch_netbsd_mapping_mapfile.c) = d1c37cabb80d92c640e6f08ef46e16a53c7c0be7
+SHA1 (patch-src_arch_netbsd_mapping_mapfile.d) = 21a75986ea2529bbbbce060430cd1f207124f7ba
+SHA1 (patch-src_arch_netbsd_mapping_mapfile.o) = d35b7eff2748ba8211d0234a6b9dc161853e7284
+SHA1 (patch-src_arch_netbsd_mapping_mapping.c) = f472162764aa4af16b1950ea5a8cbf5a67482caa
+SHA1 (patch-src_arch_netbsd_mapping_mapping.d) = 24a952af70ec49e3ffc2b86deb2548289ef0c7ae
+SHA1 (patch-src_arch_netbsd_mapping_mapshm.c) = 041702a4c2e0397334247e97185c1e80120a713e
+SHA1 (patch-src_arch_netbsd_mapping_mapshm.d) = c479eb22fe2fd6e56d4d3ab5c95924d20ca75e3c
+SHA1 (patch-src_arch_netbsd_mcontext_386-ucontext.h) = f2123cd051eebaedbefe26b2502cd790c4f607af
+SHA1 (patch-src_arch_netbsd_mcontext_COPYRIGHT) = be70d6366373b03f929ba87ddd313139d06e6191
+SHA1 (patch-src_arch_netbsd_mcontext_Makefile) = 42c723a998a2794ef7dd7cc436f1f182d5286b4b
+SHA1 (patch-src_arch_netbsd_mcontext_amd64-ucontext.h) = 5d9ae01ba6386245fa3688ada67830ee8c831c49
+SHA1 (patch-src_arch_netbsd_mcontext_asm.S) = 2c62eb7c6169aca3fd556f8cd094b7449ce25ba8
+SHA1 (patch-src_arch_netbsd_mcontext_asm.d) = c6a641d70102fcea8932d2a28ddfcb126c4443a7
+SHA1 (patch-src_arch_netbsd_mcontext_asm.o) = 6cb283d66dac91830e5b0d35df02691ebeadfbfc
+SHA1 (patch-src_arch_netbsd_mcontext_context.c) = 6159a1e21d1eddeb0ec9e137aaec352253ee8453
+SHA1 (patch-src_arch_netbsd_mcontext_context.d) = 9137c5006404bb6b684ee8d2fc9fb53bae789ef4
+SHA1 (patch-src_arch_netbsd_mcontext_context.o) = e841cc1c289e7f215bd0651461f271fdb0c244ca
+SHA1 (patch-src_arch_netbsd_mcontext_mcontext.h) = 0ce55a940c8cdda5e03e5a94a8be3e3ff521abc0
+SHA1 (patch-src_base_dev_misc_timers.c) = 6f544bd2ecf8529acfe039c57c01575e4f91161f
+SHA1 (patch-src_base_kbd__unicode_getfd.c) = 9f18ab02860be0f88191766ba0f80bea37e7c75e
+SHA1 (patch-src_base_kbd__unicode_keyb__raw.c) = adf87bc6605dc6f36cc511256786378d6d1cb283
+SHA1 (patch-src_base_kbd__unicode_keymaps.c) = b9fb1f847324ad83c2cb1e824c9933abdb507746
+SHA1 (patch-src_base_misc_libpcl_Makefile) = 0e883f487a24a026a443ecd0870dcee1bbe354f2
+SHA1 (patch-src_include_debug.h) = 26ed35f3dc7e0cceaa934e88e1f5a0ba58a46e33
diff --git a/dosemu2/patches/patch-src_arch_netbsd_Makefile.main b/dosemu2/patches/patch-src_arch_netbsd_Makefile.main
new file mode 100644
index 0000000000..47c93f8b15
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_Makefile.main
@@ -0,0 +1,286 @@
+$NetBSD$
+
+--- src/arch/netbsd/Makefile.main.orig	2017-11-02 06:34:22.908068774 +0000
++++ src/arch/netbsd/Makefile.main
+@@ -0,0 +1,281 @@
++# Makefile for Linux DOSEMU
++#
++# You should do a "make" to compile and a "make install" as root to
++# install DOSEMU.
++
++SYS = $(top_builddir)/commands
++dosemudir = $(datadir)/dosemu
++sysdir = $(DESTDIR)$(dosemudir)/$(cmdsuff)
++cmddir = $(sysdir)/dosemu
++etcdir = $(sysconfdir)/$(confdir)
++FONTS = $(wildcard $(REALTOPDIR)/etc/*.bdf)
++TFONTS = $(FONTS:$(REALTOPDIR)/etc/%.bdf=$(top_builddir)/etc/%.pcf.gz)
++
++NET=dosext/net
++
++REQUIRED=env/commands tools/periph
++
++#
++# This is defined when the SB Emulation is required. You should re-configure,
++# rather than just change this.
++#
++SBEMU=base/dev/sb16 base/sound
++
++#
++# This is defined when the CPU emulator is required. You should
++# re-configure, rather than just change this.
++#
++XCPUEMU=emu-i386/simx86
++
++# No longer need midid
++#REQUIRED += $(MIDID)
++
++DPMI = dosext/dpmi dosext/dpmi/msdos
++
++_LIBSUBDIRS=base/video base/dev/vga base/async base/kbd_unicode \
++	arch/linux/async arch/linux/mapping arch/linux/mcontext \
++	base/misc base/misc/libpcl base/dev/misc \
++	emu-i386 $(XCPUEMU) base/speaker \
++	base/dev/pic \
++	dosext/mfs dosext/misc \
++	base/init base/serial base/mouse \
++	base/dev/dma env/translate env/builtins \
++	tools/debugger \
++	$(NET) $(IPX) $(SBEMU) dosext/drivers base/bios \
++	$(DPMI)
++
++LIBSUBDIRS=$(_LIBSUBDIRS) $(PLUGINSUBDIRS)
++ST_LIBSUBDIRS=$(_LIBSUBDIRS) $(ST_PLUGINSUBDIRS)
++
++
++# call all libraries the name of the directory
++LIBS_ := ${addsuffix .a,${addprefix lib/lib,$(subst /,_,$(ST_LIBSUBDIRS))}}
++
++DOCS= $(top_builddir)/man
++
++###################################################################
++
++default: $(top_builddir)/src/include/version.h $(top_builddir)/$(PACKAGE_NAME).spec doslib \
++	$(top_builddir)/etc/xtermdos $(top_builddir)/etc/xinstallvgafont $(TFONTS)
++	@echo ""
++	@echo "---------------------------------DONE compiling-------------------------------"
++	@echo ""
++	@echo " Now you must install DOSEMU. Make sure you are root and:"
++	@echo " make install"
++	@echo ""
++	@echo ""
++
++$(top_builddir)/etc/xtermdos:	$(REALTOPDIR)/etc/xtermdos.sh
++	@echo "#!/bin/sh" > $(top_builddir)/etc/xtermdos
++	@echo >> $(top_builddir)/etc/xtermdos
++	@echo X11ROOTDIR=$(X11ROOTDIR) >> $(top_builddir)/etc/xtermdos
++	@echo >> $(top_builddir)/etc/xtermdos
++	@cat $(REALTOPDIR)/etc/xtermdos.sh >> $(top_builddir)/etc/xtermdos
++
++$(top_builddir)/etc/xinstallvgafont:	$(REALTOPDIR)/etc/xinstallvgafont.sh
++	@echo "#!/bin/sh" > $(top_builddir)/etc/xinstallvgafont
++	@echo >> $(top_builddir)/etc/xinstallvgafont
++	@echo X11ROOTDIR=$(X11ROOTDIR) >> $(top_builddir)/etc/xinstallvgafont
++	@echo >> $(top_builddir)/etc/xinstallvgafont
++	@cat $(REALTOPDIR)/etc/xinstallvgafont.sh >> $(top_builddir)/etc/xinstallvgafont
++
++$(top_builddir)/etc/%.pcf.gz: $(REALTOPDIR)/etc/%.bdf
++	bdftopcf $< | gzip -c -9 -n > $@
++
++emu.o: emu.c
++
++$(BINPATH)/bin/$(DOSBIN): emu.o $(LIBS_)
++	$(LD) $(ALL_LDFLAGS) $(DOSBIN_LDFLAGS) -o $@ emu.o \
++	   -Wl,--whole-archive $(LIBS_) -Wl,--no-whole-archive $(LIBS)
++	@nm $(BINPATH)/bin/$(DOSBIN) | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
++		sort > $(BINPATH)/bin/dosemu.map
++
++$(BINPATH)/bin/dosemu: $(SRCPATH)/bindist/dosemu.systemwide $(SRCPATH)/bindist/dosemu
++	sed -e "s|SYSTEM_BIN_PATH=NOT_SYSTEM_WIDE|SYSTEM_BIN_PATH=$(bindir)|" \
++		      $< > $(BINPATH)/bin/dosemu
++	tail -n +9 $(SRCPATH)/bindist/dosemu >> $(BINPATH)/bin/dosemu
++	chmod +x $(BINPATH)/bin/dosemu
++
++bin: $(top_builddir)/bin $(BINPATH)/bin/$(DOSBIN) $(BINPATH)/bin/dosemu
++
++# This recursive call seems to be necessary to deal with parallel makes.
++# Otherwise the rule for $(DOSBIN) would depend on a phony target, and
++# this does not seem to be supported by GNU Make.
++dosemu: $(LIBSUBDIRS)
++	@$(MAKE) bin
++
++DIRLIST=$(REQUIRED) $(DOCS) $(LIBSUBDIRS) $(OPTIONALSUBDIRS)
++.PHONY:	dossubdirs optionalsubdirs docsubdirs dosemu bin
++.PHONY: $(DIRLIST)
++
++optionalsubdirs:	$(OPTIONALSUBDIRS)
++
++docsubdirs:	$(DOCS)
++
++$(DIRLIST):
++	@($(MAKE) SUBDIR:=$@ -C $@)
++
++doslib: $(REQUIRED) $(DOCS) dosemu
++
++installnew: doslib
++	$(MAKE) install
++
++install:
++	$(INSTALL) -d $(DESTDIR)$(dosemudir)
++	-rm -rf $(DESTDIR)$(dosemudir)/commands $(DESTDIR)$(dosemudir)/freedos/dosemu
++	-rm -rf $(DESTDIR)$(dosemudir)/drive_z
++	-rm -rf $(cmddir)
++	-rm -rf $(sysdir)
++	$(INSTALL) -d $(DESTDIR)$(etcdir)
++	cd $(REALTOPDIR); \
++	if [ -n "$(fdtarball)" -a -f "$(fdtarball)" ]; then \
++	  rm -rf $(DESTDIR)$(dosemudir)/freedos; \
++	  tar -C $(DESTDIR)$(dosemudir)/.. --no-same-owner -xpzvf $(fdtarball); \
++	  rm -f $(DESTDIR)$(dosemudir)/FDchange.log; \
++	  rm -f $(DESTDIR)$(dosemudir)/README.bindist; \
++	  rm -rf $(DESTDIR)$(dosemudir)/freedos/tmp; \
++	fi
++	if [ -d $(DESTDIR)$(dosemudir)/freedos ]; then \
++	  ln -sf freedos $(DESTDIR)$(dosemudir)/drive_z; \
++	  ln -sf /tmp $(DESTDIR)$(dosemudir)/freedos/tmp; \
++	else \
++	  $(INSTALL) -d $(DESTDIR)$(dosemudir)/drive_z; \
++	fi
++	$(INSTALL) -d $(sysdir)
++	$(INSTALL) -m 0644 $(SRCPATH)/bindist/config.sys $(sysdir)
++	$(INSTALL) -m 0644 $(SRCPATH)/bindist/autoexec.bat $(sysdir)
++	$(INSTALL) -m 0644 $(SRCPATH)/bindist/fdconfig.sys $(sysdir)
++	$(INSTALL) -m 0644 $(SRCPATH)/bindist/autoemu.bat $(sysdir)
++	$(INSTALL) -d $(cmddir)
++	for i in `find $(SYS)/* -type f`; do \
++	  $(INSTALL) -m 0644 $$i $(cmddir); \
++	done
++	cd $(SYS); for i in `find * -type l`; do \
++	  ln -sf generic.com $(cmddir)/$$i; \
++	done
++	ln -sf $(cmdsuff) $(DESTDIR)$(dosemudir)/commands
++	ln -sf ../$(cmdsuff)/dosemu $(DESTDIR)$(dosemudir)/drive_z/dosemu
++	if [ ! -f $(DESTDIR)$(etcdir)/dosemu.conf ]; then \
++	  $(INSTALL) -m 0644 $(REALTOPDIR)/etc/dosemu.conf $(DESTDIR)$(etcdir); \
++	fi
++	$(INSTALL) -d $(DESTDIR)$(dosemudir)/keymap
++	for i in $(REALTOPDIR)/etc/keymap/*; do \
++	  if [ -f $$i ]; then \
++	    $(INSTALL) -m 0644 $$i $(DESTDIR)$(dosemudir)/keymap; \
++	  fi; \
++	done
++	$(INSTALL) -d $(DESTDIR)$(dosemudir)/icons
++	for i in $(REALTOPDIR)/etc/*.xpm; do \
++	  if [ -f $$i ]; then \
++	    $(INSTALL) -m 0644 $$i $(DESTDIR)$(dosemudir)/icons; \
++	  fi; \
++	done
++	$(INSTALL) -d $(DESTDIR)$(bindir)
++	$(INSTALL) -m 0755 $(top_builddir)/bin/$(DOSBIN) $(DESTDIR)$(bindir)
++	$(INSTALL) -m 0755 $(top_builddir)/bin/dosemu $(DESTDIR)$(bindir)
++	$(INSTALL) -m 0755 $(top_builddir)/bin/mkfatimage16 $(DESTDIR)$(bindir)
++	$(INSTALL) -m 0755 $(top_builddir)/bin/dosdebug $(DESTDIR)$(bindir)
++	$(INSTALL) -d $(DESTDIR)$(plugindir)
++	for i in $(top_builddir)/bin/*.so; do \
++	  if [ -f $$i ]; then \
++	    $(INSTALL) -m 0644 $$i $(DESTDIR)$(plugindir); \
++	  fi; \
++	done
++	$(INSTALL) -d $(DESTDIR)$(docdir)
++	for i in README.bindist NEWS THANKS BUGS changelog; do \
++	    $(INSTALL) -m 0644 $(top_builddir)/$$i $(DESTDIR)$(docdir); \
++	done
++	for i in README EMUfailure tweaks; do \
++	  $(INSTALL) -m 0644 $(REALTOPDIR)/doc/$$i.html $(DESTDIR)$(docdir); \
++	done
++	$(INSTALL) -m 0644 $(REALTOPDIR)/doc/NOVELL-HOWTO.txt $(DESTDIR)$(docdir)
++	$(INSTALL) -m 0644 $(REALTOPDIR)/doc/README.gdb $(DESTDIR)$(docdir)
++	$(INSTALL) -d $(DESTDIR)$(x11fontdir)
++	echo "-> Installing the X PC fonts..."
++	for i in $(top_builddir)/etc/*.pcf.gz; do \
++	    install -m 0644 $$i $(DESTDIR)$(x11fontdir); \
++	done
++	$(INSTALL) -m 0644 $(REALTOPDIR)/etc/$(PACKAGE_NAME).alias $(DESTDIR)$(x11fontdir)/fonts.alias; \
++	mkfontdir $(DESTDIR)$(x11fontdir)
++	if [ -d "$(DESTDIR)$(sysconfdir)/X11/fontpath.d" ]; then \
++	    rm -f $(DESTDIR)$(sysconfdir)/X11/fontpath.d/$(PACKAGE_NAME):unscaled:pri=20; \
++	    ln -sf $(x11fontdir) $(DESTDIR)$(sysconfdir)/X11/fontpath.d/$(PACKAGE_NAME):unscaled:pri=20; \
++	fi
++
++	echo "-> Installing man pages..."
++	$(MAKE) -C $(top_builddir)/man install
++	@if test $(etcdir) != /etc; then \
++	  if [ -f $(DESTDIR)/etc/dosemu.users ]; then \
++	    echo ; \
++	    echo /etc/dosemu.users exists but you did not set etcdir=/etc; \
++	    echo Deprecated: moving to /etc/dosemu/dosemu.users; \
++	    echo mv /etc/dosemu.users /etc/dosemu/dosemu.users; \
++	    mv /etc/dosemu.users /etc/dosemu/dosemu.users; \
++	  fi; \
++	  if [ -f $(DESTDIR)/etc/dosemu.conf ]; then \
++	    echo ; \
++	    echo /etc/dosemu.conf exists but you did not set etcdir=/etc; \
++	    echo Deprecated: moving to /etc/dosemu/dosemu.conf; \
++	    echo mv /etc/dosemu.conf /etc/dosemu/dosemu.conf; \
++	    mv /etc/dosemu.conf /etc/dosemu/dosemu.conf; \
++	  fi \
++	fi
++	@echo ""; \
++	 echo "---------------------------------DONE Installing-------------------------------"; \
++	 echo ""
++	@cd $(REALTOPDIR); if test -n "$(fdtarball)" -a ! -f "$(fdtarball)"; then \
++	  echo WARNING ;\
++	  echo No FreeDOS tarball \($(fdtarball)\);\
++	  echo found. If you are not ;\
++	  echo upgrading a working existing installation then please download one ;\
++	  echo from http://www.dosemu.org and re-run "make install".; \
++	  echo You can also use this procedure to upgrade an existing *FreeDOS*; \
++	  echo installation when a new tarball is available.; \
++	  echo Alternatively you can set fdtarball to none in compiletime-settings; \
++	  echo and use another DOS, which can be installed using dosemu -install,; \
++	  echo referred to using \$$_hdimage in $(etcdir)/dosemu.conf or \~/.dosemurc; \
++	  echo or symbolically linked from \~/.dosemu/drives/c.; \
++	  echo ; \
++	fi
++	@echo "  - You can type 'dosemu' to run DOSEMU. If you installed the FreeDOS tarball"; \
++	 echo "    too (see the warning above), then DOSEMU will set up a directory structure"; \
++	 echo "    in your home directory when you run it for the first time."
++
++uninstall:
++	rm -rf $(DESTDIR)$(dosemudir)
++	rm -f $(DESTDIR)$(bindir)/$(DOSBIN)
++	rm -f $(DESTDIR)$(bindir)/dosemu
++	rm -f $(DESTDIR)$(bindir)/mkfatimage16
++	rm -f $(DESTDIR)$(bindir)/mkhdimage
++	rm -f $(DESTDIR)$(bindir)/dosdebug
++	rm -rf $(DESTDIR)$(plugindir)
++	rm -rf $(DESTDIR)$(docdir)
++	ls $(DOCS)/*.1 | xargs --max-args=1 basename | xargs -I {} --max-args=1 rm -f $(DESTDIR)$(mandir)/man1/{}
++	ls $(DOCS)/ru/*.1 | xargs --max-args=1 basename | xargs -I {} --max-args=1 rm -f $(DESTDIR)$(mandir)/ru/man1/{}
++
++local_clean:
++	rm -f $(top_builddir)/bin $(top_builddir)/commands
++
++clean:: local_clean
++
++realclean:: local_clean
++	rm -rf $(BINPATH)
++
++CLEANDIRS=$(addsuffix .clean, $(DIRLIST))
++REALCLEANDIRS=$(addsuffix .realclean, $(DIRLIST))
++
++clean:: $(CLEANDIRS)
++
++realclean:: $(REALCLEANDIRS)
++
++.PHONY: $(CLEANDIRS)
++$(CLEANDIRS):
++	-@$(MAKE) -C $(subst .clean,,$@) clean CLEANING=true
++
++.PHONY: $(REALCLEANDIRS)
++$(REALCLEANDIRS):
++	-@$(MAKE) -C $(subst .realclean,,$@) realclean CLEANING=true
++
++pristine:	realclean
++	-rm -rf lib
++	-rm -rf $(BINPATH) $(top_builddir)/bin $(top_builddir)/commands $(top_builddir)/etc/xtermdos $(top_builddir)/etc/xinstallvgafont $(top_builddir)/etc/*.pcf.gz $(top_builddir)/etc/fonts.dir
diff --git a/dosemu2/patches/patch-src_arch_netbsd_async_Makefile b/dosemu2/patches/patch-src_arch_netbsd_async_Makefile
new file mode 100644
index 0000000000..5c9c1e0315
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_async_Makefile
@@ -0,0 +1,18 @@
+$NetBSD$
+
+--- src/arch/netbsd/async/Makefile.orig	2017-11-02 06:34:33.811925841 +0000
++++ src/arch/netbsd/async/Makefile
+@@ -0,0 +1,13 @@
++top_builddir=../../../..
++include $(top_builddir)/Makefile.conf
++
++CFILES=sigsegv.c signal.c debug.c
++ifeq ($(HAVE_LIBBFD),1)
++CFILES += backtrace-symbols.c
++endif
++
++ALL_CPPFLAGS += -I$(REALTOPDIR)/src/arch/linux/mcontext
++
++include $(REALTOPDIR)/src/Makefile.common
++
++all: lib
diff --git a/dosemu2/patches/patch-src_arch_netbsd_async_backtrace-symbols.c b/dosemu2/patches/patch-src_arch_netbsd_async_backtrace-symbols.c
new file mode 100644
index 0000000000..896c61d415
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_async_backtrace-symbols.c
@@ -0,0 +1,333 @@
+$NetBSD$
+
+--- src/arch/netbsd/async/backtrace-symbols.c.orig	2017-11-02 06:34:33.812823967 +0000
++++ src/arch/netbsd/async/backtrace-symbols.c
+@@ -0,0 +1,328 @@
++/*
++  A hacky replacement for backtrace_symbols in glibc
++
++  backtrace_symbols in glibc looks up symbols using dladdr which is limited in
++  the symbols that it sees. libbacktracesymbols opens the executable and shared
++  libraries using libbfd and will look up backtrace information using the symbol
++  table and the dwarf line information.
++
++  It may make more sense for this program to use libelf instead of libbfd.
++  However, I have not investigated that yet.
++
++  Derived from addr2line.c from GNU Binutils by Jeff Muizelaar
++
++  Copyright 2007 Jeff Muizelaar
++*/
++
++/* addr2line.c -- convert addresses to line number and function name
++   Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
++   Contributed by Ulrich Lauther <Ulrich.Lauther%mchp.siemens.de@localhost>
++
++   This file was part of GNU Binutils.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2, or (at your option)
++   any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.  */
++
++#define fatal(a, b) exit(1)
++#define bfd_fatal(a) exit(1)
++#define bfd_nonfatal(a) exit(1)
++#define list_matching_formats(a) exit(1)
++
++/* 2 characters for each byte, plus 1 each for 0, x, and NULL */
++#define PTRSTR_LEN (sizeof(void *) * 2 + 3)
++#define true 1
++#define false 0
++
++#include <string.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <execinfo.h>
++/* hack for some versions of bfd.h that require PACKAGE to be defined */
++#ifndef PACKAGE
++ #define PACKAGE
++ #ifndef PACKAGE_VERSION
++  #define PACKAGE_VERSION
++  #include <bfd.h>
++  #undef PACKAGE_VERSION
++ #else
++  #include <bfd.h>
++ #endif
++ #undef PACKAGE
++#else
++ #ifndef PACKAGE_VERSION
++  #define PACKAGE_VERSION
++  #include <bfd.h>
++  #undef PACKAGE_VERSION
++ #else
++  #include <bfd.h>
++ #endif
++#endif
++#include <dlfcn.h>
++#include <link.h>
++
++
++static asymbol **syms;		/* Symbol table.  */
++
++/* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
++#define OPTION_DEMANGLER	(150)
++
++static void slurp_symtab(bfd * abfd);
++static void find_address_in_section(bfd *abfd, asection *section, void *data);
++
++/* Read in the symbol table.  */
++
++static void slurp_symtab(bfd * abfd)
++{
++	long symcount;
++	unsigned int size;
++
++	if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
++		return;
++
++	symcount = bfd_read_minisymbols(abfd, false, (PTR) & syms, &size);
++	if (symcount == 0)
++		symcount = bfd_read_minisymbols(abfd, true /* dynamic */ ,
++						(PTR) & syms, &size);
++
++	if (symcount < 0)
++		bfd_fatal(bfd_get_filename(abfd));
++}
++
++/* These global variables are used to pass information between
++   translate_addresses and find_address_in_section.  */
++
++static bfd_vma pc;
++static const char *filename;
++static const char *functionname;
++static unsigned int line;
++static int found;
++
++/* Look for an address in a section.  This is called via
++   bfd_map_over_sections.  */
++
++static void find_address_in_section(bfd *abfd, asection *section, void *data __attribute__ ((__unused__)) )
++{
++	bfd_vma vma;
++	bfd_size_type size;
++
++	if (found)
++		return;
++
++	if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
++		return;
++
++	vma = bfd_get_section_vma(abfd, section);
++	if (pc < vma)
++		return;
++
++	size = bfd_section_size(abfd, section);
++	if (pc >= vma + size)
++		return;
++
++	found = bfd_find_nearest_line(abfd, section, syms, pc - vma,
++				      &filename, &functionname, &line);
++}
++
++static char** translate_addresses_buf(bfd * abfd, bfd_vma *addr, int naddr)
++{
++	int naddr_orig = naddr;
++	char b;
++	int total  = 0;
++	enum { Count, Print } state;
++	char *buf = &b;
++	int len = 0;
++	char **ret_buf = NULL;
++	/* iterate over the formating twice.
++	 * the first time we count how much space we need
++	 * the second time we do the actual printing */
++	for (state=Count; state<=Print; state++) {
++	if (state == Print) {
++		ret_buf = malloc(total + sizeof(char*)*naddr);
++		buf = (char*)(ret_buf + naddr);
++		len = total;
++	}
++	while (naddr) {
++		if (state == Print)
++			ret_buf[naddr-1] = buf;
++		pc = addr[naddr-1];
++
++		found = false;
++		bfd_map_over_sections(abfd, find_address_in_section,
++		(PTR) NULL);
++
++		if (!found) {
++			total += snprintf(buf, len, "[0x%llx] \?\?() \?\?:0",(long long unsigned int) addr[naddr-1]) + 1;
++		} else {
++			const char *name;
++
++			name = functionname;
++			if (name == NULL || *name == '\0')
++				name = "??";
++			if (filename != NULL) {
++				char *h;
++
++				h = strrchr(filename, '/');
++				if (h != NULL)
++					filename = h + 1;
++			}
++			total += snprintf(buf, len, "%s:%u\t%s()", filename ? filename : "??",
++			       line, name) + 1;
++
++		}
++		if (state == Print) {
++			/* set buf just past the end of string */
++			buf = buf + total + 1;
++		}
++		naddr--;
++	}
++	naddr = naddr_orig;
++	}
++	return ret_buf;
++}
++/* Process a file.  */
++
++static char **process_file(const char *file_name, bfd_vma *addr, int naddr)
++{
++	bfd *abfd;
++	char **matching;
++	char **ret_buf;
++
++	abfd = bfd_openr(file_name, NULL);
++
++	if (abfd == NULL)
++		bfd_fatal(file_name);
++
++	if (bfd_check_format(abfd, bfd_archive))
++		fatal("%s: can not get addresses from archive", file_name);
++
++	if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
++		bfd_nonfatal(bfd_get_filename(abfd));
++		if (bfd_get_error() ==
++		    bfd_error_file_ambiguously_recognized) {
++			list_matching_formats(matching);
++			free(matching);
++		}
++		exit(1);
++	}
++
++	slurp_symtab(abfd);
++
++	ret_buf = translate_addresses_buf(abfd, addr, naddr);
++
++	if (syms != NULL) {
++		free(syms);
++		syms = NULL;
++	}
++
++	bfd_close(abfd);
++	return ret_buf;
++}
++
++#define MAX_DEPTH 16
++
++struct file_match {
++	const char *file;
++	ElfW(Addr) address;
++	ElfW(Addr) base;
++};
++
++static int find_matching_file(struct dl_phdr_info *info,
++		size_t __attribute__((unused)) size, void *data)
++{
++	struct file_match *match = data;
++	/* This code is modeled from Gfind_proc_info-lsb.c:callback() from libunwind */
++	long n;
++	const ElfW(Phdr) *phdr;
++	ElfW(Addr) load_base = info->dlpi_addr;
++	phdr = info->dlpi_phdr;
++	for (n = info->dlpi_phnum; --n >= 0; phdr++) {
++		if (phdr->p_type == PT_LOAD) {
++			ElfW(Addr) vaddr = phdr->p_vaddr + load_base;
++			if (match->address >= vaddr && match->address < vaddr + phdr->p_memsz) {
++				/* we found a match */
++				match->file = info->dlpi_name;
++				match->base = info->dlpi_addr;
++			}
++		}
++	}
++	return 0;
++}
++
++char **backtrace_symbols(void *const *buffer, int size)
++{
++	int stack_depth = size - 1;
++	int x,y;
++	/* discard calling function */
++	int total = 0;
++
++	char ***locations;
++	char **final;
++	char *f_strings;
++
++	locations = malloc(sizeof(char**) * (stack_depth+1));
++
++	bfd_init();
++	for(x=stack_depth, y=0; x>=0; x--, y++){
++		struct file_match match = { .address = (ElfW(Addr))buffer[x] };
++		char **ret_buf;
++		bfd_vma addr;
++		dl_iterate_phdr(find_matching_file, &match);
++		addr = (ElfW(Addr))buffer[x] - match.base;
++		if (match.file && match.file[0] == '/')
++			ret_buf = process_file(match.file, &addr, 1);
++		else
++			ret_buf = process_file("/proc/self/exe", &addr, 1);
++		locations[x] = ret_buf;
++		total += strlen(ret_buf[0]) + 1;
++	}
++
++	/* allocate the array of char* we are going to return and extra space for
++	 * all of the strings */
++	final = malloc(total + (stack_depth + 1) * sizeof(char*));
++	/* get a pointer to the extra space */
++	f_strings = (char*)(final + stack_depth + 1);
++
++	/* fill in all of strings and pointers */
++	for(x=stack_depth; x>=0; x--){
++		strcpy(f_strings, locations[x][0]);
++		free(locations[x]);
++		final[x] = f_strings;
++		f_strings += strlen(f_strings) + 1;
++	}
++
++	free(locations);
++
++	return final;
++}
++
++void
++backtrace_symbols_fd(void *const *buffer, int size, int fd)
++{
++        int j;
++        char **strings;
++
++        strings = backtrace_symbols(buffer, size);
++        if (strings == NULL) {
++		perror("backtrace_symbols");
++		exit(EXIT_FAILURE);
++        }
++
++        for (j = 0; j < size; j++) {
++		write(fd, strings[j], strlen(strings[j]));
++		write(fd, "\n", 1);
++	}
++
++        free(strings);
++}
diff --git a/dosemu2/patches/patch-src_arch_netbsd_async_debug.c b/dosemu2/patches/patch-src_arch_netbsd_async_debug.c
new file mode 100644
index 0000000000..7ab73597ff
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_async_debug.c
@@ -0,0 +1,221 @@
+$NetBSD$
+
+--- src/arch/netbsd/async/debug.c.orig	2017-11-02 06:34:33.813702898 +0000
++++ src/arch/netbsd/async/debug.c
+@@ -0,0 +1,216 @@
++#include "emu.h"
++#include "dosemu_config.h"
++#include "debug.h"
++#include "sig.h"
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <assert.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <execinfo.h>
++
++static FILE *gdb_f = NULL;
++
++static void gdb_command(char *cmd)
++{
++  printf("%s", cmd);
++  fflush(stdout);
++  fprintf(gdb_f, "%s", cmd);
++  fflush(gdb_f);
++}
++
++static int start_gdb(pid_t dosemu_pid)
++{
++  char *buf;
++  int ret;
++
++  printf("Debug info:\n");
++  fflush(stdout);
++
++  ret = asprintf(&buf, "gdb %s", dosemu_proc_self_exe);
++  assert(ret != -1);
++
++  printf("%s", buf);
++  putchar('\n');
++  fflush(stdout);
++
++  if (!(gdb_f = popen(buf, "w"))) {
++    free(buf);
++    return 0;
++  }
++  free(buf);
++
++  ret = asprintf(&buf, "attach %i\n", dosemu_pid);
++  assert(ret != -1);
++
++  gdb_command(buf);
++  free(buf);
++
++  return 1;
++}
++
++static void do_debug(void)
++{
++  char *cmd1 = "info registers\n";
++//  char *cmd2 = "backtrace\n";
++  char *cmd3 = "thread apply all backtrace full\n";
++
++  gdb_command(cmd1);
++//  gdb_command(cmd2);
++  gdb_command(cmd3);
++}
++
++static int stop_gdb(void)
++{
++  char *cmd1 = "detach\n";
++  char *cmd2 = "quit\n";
++  int status;
++
++  gdb_command(cmd1);
++  gdb_command(cmd2);
++  wait(&status);
++  pclose(gdb_f);
++  putchar('\n');
++  fflush(stdout);
++  return !WEXITSTATUS(status);
++}
++
++/* disable as this crashes under DPMI trying to trace through DOS stack */
++/* ... and re-enable because people fuck up instead of installing gdb.
++ * But run this only if the gdb trace fails. */
++#if 1
++/* Obtain a backtrace and print it to `stdout'.
++   (derived from 'info libc')
++ */
++static void print_trace (void)
++{
++#define MAX_FRAMES 256
++  void *array[MAX_FRAMES];
++  int size;
++  char **strings;
++  size_t i;
++
++  size = backtrace (array, MAX_FRAMES);
++  strings = backtrace_symbols (array, size);
++  fprintf(dbg_fd, "Obtained %d stack frames.\n", size);
++
++  for (i = 0; i < size; i++)
++    fprintf(dbg_fd, "%s\n", strings[i]);
++
++  free (strings);
++  fprintf(dbg_fd, "Backtrace finished\n");
++}
++#endif
++
++static void collect_info(pid_t pid)
++{
++  char *cmd0 = "ldd %s";
++  char *cmd1 = "getconf GNU_LIBC_VERSION";
++  char *cmd2 = "getconf GNU_LIBPTHREAD_VERSION";
++  char *cmd3 = "cat /proc/%i/maps";
++  char *tmp;
++  int ret;
++
++  printf("System info:\n");
++  fflush(stdout);
++
++  ret = asprintf(&tmp, cmd0, dosemu_proc_self_exe);
++  assert(ret != -1);
++
++  if(system(tmp)) {
++    printf("command '%s' failed\n", tmp);
++  }
++  free(tmp);
++
++  if(system(cmd1)) {
++    printf("command '%s' failed\n", cmd1);
++  }
++
++  if(system(cmd2)) {
++    printf("command '%s' failed\n", cmd2);
++  }
++
++  ret = asprintf(&tmp, cmd3, pid);
++  assert(ret != -1);
++
++  if(system(tmp)) {
++    printf("command '%s' failed\n", tmp);
++  }
++  free(tmp);
++
++  fflush(stdout);
++}
++
++static int do_gdb_debug(void)
++{
++  int ret = 0;
++  pid_t dosemu_pid = getpid();
++  pid_t dbg_pid;
++  int status;
++  sigset_t set, oset;
++
++  if (getuid() != geteuid())
++    return 0;
++
++  sigemptyset(&set);
++  sigaddset(&set, SIGIO);
++  sigaddset(&set, SIGALRM);
++  sigprocmask(SIG_BLOCK, &set, &oset);
++  switch ((dbg_pid = fork())) {
++    case 0:
++      ioselect_done();
++      signal_done();
++      sigprocmask(SIG_SETMASK, &oset, NULL);
++
++      dup2(fileno(dbg_fd), STDOUT_FILENO);
++      dup2(fileno(dbg_fd), STDERR_FILENO);
++
++      collect_info(dosemu_pid);
++
++      if (!start_gdb(dosemu_pid))
++        _exit(1);
++      do_debug();
++      if (!stop_gdb())
++        _exit(1);
++      _exit(0);
++      break;
++    case -1:
++      error("fork failed, %s\n", strerror(errno));
++      break;
++    default:
++      waitpid(dbg_pid, &status, 0);
++      if (WEXITSTATUS(status)) {
++        dbug_printf("backtrace failure\n");
++      } else {
++        ret = 1;
++        dbug_printf("done backtrace\n");
++      }
++      break;
++  }
++  sigprocmask(SIG_SETMASK, &oset, NULL);
++  return ret;
++}
++
++void gdb_debug(void)
++{
++    int ret = do_gdb_debug();
++#if 0
++    if (!ret) {
++        print_trace();
++        error("Please install gdb!\n");
++    }
++#else
++    /* the problem with the above is that gdb usually doesn't work
++     * because of the security restrictions */
++    if (!ret)
++        error("Please install gdb!\n");
++    print_trace();
++#endif
++
++    fprintf(dbg_fd, "\n");
++    fflush(dbg_fd);
++    dump_state();
++}
diff --git a/dosemu2/patches/patch-src_arch_netbsd_async_debug.h b/dosemu2/patches/patch-src_arch_netbsd_async_debug.h
new file mode 100644
index 0000000000..318f0b1f09
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_async_debug.h
@@ -0,0 +1,11 @@
+$NetBSD$
+
+--- src/arch/netbsd/async/debug.h.orig	2017-11-02 06:34:33.814576267 +0000
++++ src/arch/netbsd/async/debug.h
+@@ -0,0 +1,6 @@
++#ifndef __DEBUG_H
++#define __DEBUG_H
++
++void gdb_debug(void);
++
++#endif
diff --git a/dosemu2/patches/patch-src_arch_netbsd_async_signal.c b/dosemu2/patches/patch-src_arch_netbsd_async_signal.c
new file mode 100644
index 0000000000..d157fa705f
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_async_signal.c
@@ -0,0 +1,1215 @@
+$NetBSD$
+
+--- src/arch/netbsd/async/signal.c.orig	2017-11-02 06:34:33.815443408 +0000
++++ src/arch/netbsd/async/signal.c
+@@ -0,0 +1,1210 @@
++#include "config.h"
++
++#include <stdio.h>
++#include <termios.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <signal.h>
++#include <string.h>
++#include <errno.h>
++#include <inttypes.h>
++#include <pthread.h>
++#include <sys/eventfd.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <sys/mman.h>
++#include <assert.h>
++#include <linux/version.h>
++
++#include "emu.h"
++#ifdef __linux__
++#include "sys_vm86.h"
++#endif
++#include "bios.h"
++#include "mouse.h"
++#include "video.h"
++#include "vgaemu.h"
++#include "vgatext.h"
++#include "render.h"
++#include "timers.h"
++#include "int.h"
++#include "lowmem.h"
++#include "coopth.h"
++#include "dpmi.h"
++#include "pic.h"
++#include "ipx.h"
++#include "pktdrvr.h"
++#include "iodev.h"
++#include "serial.h"
++#include "debug.h"
++#include "mhpdbg.h"
++#include "utilities.h"
++#include "userhook.h"
++#include "ringbuf.h"
++#include "dosemu_config.h"
++#include "sound.h"
++#include "cpu-emu.h"
++#include "sig.h"
++
++#define SIGALTSTACK_WA_DEFAULT 1
++#if SIGALTSTACK_WA_DEFAULT
++  #ifdef DISABLE_SYSTEM_WA
++    #ifdef SS_AUTODISARM
++      #define SIGALTSTACK_WA 0
++    #else
++      #ifdef WARN_UNDISABLED_WA
++        #warning Not disabling SIGALTSTACK_WA, update your kernel
++      #endif
++      #define SIGALTSTACK_WA 1
++    #endif
++  #else
++    /* work-around sigaltstack badness - disable when kernel is fixed */
++    #define SIGALTSTACK_WA 1
++  #endif
++  #if defined(WARN_OUTDATED_WA) && defined(SS_AUTODISARM)
++    #warning SIGALTSTACK_WA is outdated
++  #endif
++#else
++  #define SIGALTSTACK_WA 0
++#endif
++#if SIGALTSTACK_WA
++#include "mcontext.h"
++#include "mapping.h"
++#endif
++/* SS_AUTODISARM is a dosemu-specific sigaltstack extension supported
++ * by some kernels */
++#ifndef SS_AUTODISARM
++#define SS_AUTODISARM  (1U << 31)    /* disable sas during sighandling */
++#endif
++
++#ifdef __x86_64__
++  #define SIGRETURN_WA_DEFAULT 1
++#else
++  #define SIGRETURN_WA_DEFAULT 0
++#endif
++#if SIGRETURN_WA_DEFAULT
++  #ifdef DISABLE_SYSTEM_WA
++    #ifdef UC_SIGCONTEXT_SS
++      #define SIGRETURN_WA 0
++    #else
++      #ifdef WARN_UNDISABLED_WA
++        #warning Not disabling SIGRETURN_WA, update your kernel
++      #endif
++      #define SIGRETURN_WA 1
++    #endif
++  #else
++    /* work-around sigreturn badness - disable when kernel is fixed */
++    #define SIGRETURN_WA 1
++  #endif
++  #if defined(WARN_OUTDATED_WA) && defined(UC_SIGCONTEXT_SS)
++    #warning SIGRETURN_WA is outdated
++  #endif
++#else
++  #define SIGRETURN_WA 0
++#endif
++
++/* Variables for keeping track of signals */
++#define MAX_SIG_QUEUE_SIZE 50
++#define MAX_SIG_DATA_SIZE 128
++static u_short SIGNAL_head=0; u_short SIGNAL_tail=0;
++struct  SIGNAL_queue {
++  void (*signal_handler)(void *);
++  char arg[MAX_SIG_DATA_SIZE];
++  size_t arg_size;
++  const char *name;
++};
++static struct SIGNAL_queue signal_queue[MAX_SIG_QUEUE_SIZE];
++
++#define MAX_SIGCHLD_HANDLERS 10
++struct sigchld_hndl {
++  pid_t pid;
++  void (*handler)(void);
++  int enabled;
++};
++static struct sigchld_hndl chld_hndl[MAX_SIGCHLD_HANDLERS];
++static int chd_hndl_num;
++
++#define MAX_SIGALRM_HANDLERS 50
++struct sigalrm_hndl {
++  void (*handler)(void);
++};
++static struct sigalrm_hndl alrm_hndl[MAX_SIGALRM_HANDLERS];
++static int alrm_hndl_num;
++
++static sigset_t q_mask;
++static sigset_t nonfatal_q_mask;
++static sigset_t fatal_q_mask;
++static void *cstack;
++#if SIGALTSTACK_WA
++static void *backup_stack;
++static int need_sas_wa;
++#endif
++#if SIGRETURN_WA
++static int need_sr_wa;
++#endif
++static int block_all_sigs;
++
++static int sh_tid;
++static int in_handle_signals;
++static void handle_signals_force_enter(int tid, int sl_state);
++static void handle_signals_force_leave(int tid);
++static void async_awake(void *arg);
++static int event_fd;
++static struct rng_s cbks;
++#define MAX_CBKS 1000
++static pthread_mutex_t cbk_mtx = PTHREAD_MUTEX_INITIALIZER;
++
++struct eflags_fs_gs eflags_fs_gs;
++
++static void (*sighandlers[NSIG])(struct sigcontext *, siginfo_t *);
++static void (*qsighandlers[NSIG])(int sig, siginfo_t *si, void *uc);
++
++static void sigalrm(struct sigcontext *, siginfo_t *);
++static void sigio(struct sigcontext *, siginfo_t *);
++static void sigasync(int sig, siginfo_t *si, void *uc);
++static void leavedos_sig(int sig);
++
++static void _newsetqsig(int sig, void (*fun)(int sig, siginfo_t *si, void *uc))
++{
++	if (qsighandlers[sig])
++		return;
++	/* collect this mask so that all async (fatal and non-fatal)
++	 * signals can be blocked by threads */
++	sigaddset(&q_mask, sig);
++	qsighandlers[sig] = fun;
++}
++
++static void newsetqsig(int sig, void (*fun)(int sig, siginfo_t *si, void *uc))
++{
++#if SIGRETURN_WA
++	sigaddset(&fatal_q_mask, sig);
++#endif
++	_newsetqsig(sig, fun);
++}
++
++static void qsig_init(void)
++{
++	struct sigaction sa;
++	int i;
++
++	sa.sa_flags = SA_RESTART | SA_ONSTACK | SA_SIGINFO;
++	if (block_all_sigs)
++	{
++		/* initially block all async signals. */
++		sa.sa_mask = q_mask;
++	}
++	else
++	{
++		/* block all non-fatal async signals */
++		sa.sa_mask = nonfatal_q_mask;
++	}
++	for (i = 0; i < NSIG; i++) {
++		if (qsighandlers[i]) {
++			sa.sa_sigaction = qsighandlers[i];
++			sigaction(i, &sa, NULL);
++		}
++	}
++}
++
++/* registers non-emergency async signals */
++void registersig(int sig, void (*fun)(struct sigcontext *, siginfo_t *))
++{
++	/* first need to collect the mask, then register all handlers
++	 * because the same mask of non-emergency async signals
++	 * is used for every handler */
++	sigaddset(&nonfatal_q_mask, sig);
++	_newsetqsig(sig, sigasync);
++	sighandlers[sig] = fun;
++}
++
++static void newsetsig(int sig, void (*fun)(int sig, siginfo_t *si, void *uc))
++{
++	struct sigaction sa;
++
++	sa.sa_flags = SA_RESTART | SA_ONSTACK | SA_SIGINFO;
++	if (kernel_version_code >= KERNEL_VERSION(2, 6, 14))
++		sa.sa_flags |= SA_NODEFER;
++	if (block_all_sigs)
++	{
++		/* initially block all async signals. */
++		sa.sa_mask = q_mask;
++	}
++	else
++	{
++		/* block all non-fatal async signals */
++		sa.sa_mask = nonfatal_q_mask;
++	}
++	sa.sa_sigaction = fun;
++	sigaction(sig, &sa, NULL);
++}
++
++/* init_handler puts the handler in a sane state that glibc
++   expects. That means restoring fs and gs for vm86 (necessary for
++   2.4 kernels) and fs, gs and eflags for DPMI. */
++SIG_PROTO_PFX
++static void __init_handler(struct sigcontext *scp, int async)
++{
++#ifdef __x86_64__
++  unsigned short __ss;
++#endif
++  /*
++   * FIRST thing to do in signal handlers - to avoid being trapped into int0x11
++   * forever, we must restore the eflags.
++   */
++  loadflags(eflags_fs_gs.eflags);
++
++#ifdef __x86_64__
++  /* ds,es, and ss are ignored in 64-bit mode and not present or
++     saved in the sigcontext, so we need to do it ourselves
++     (using the 3 high words of the trapno field).
++     fs and gs are set to 0 in the sigcontext, so we also need
++     to save those ourselves */
++  _ds = getsegment(ds);
++  _es = getsegment(es);
++  /* some kernels save and switch ss, some do not... The simplest
++   * thing is to assume that if the ss is from GDT, then it is already
++   * saved. */
++  __ss = getsegment(ss);
++  if (DPMIValidSelector(__ss))
++    _ss = __ss;
++  _fs = getsegment(fs);
++  _gs = getsegment(gs);
++  if (_cs == 0) {
++      if (config.dpmi && config.cpuemu < 4) {
++	fprintf(stderr, "Cannot run DPMI code natively ");
++	if (kernel_version_code < KERNEL_VERSION(2, 6, 15))
++	  fprintf(stderr, "because your Linux kernel is older than version 2.6.15.\n");
++	else
++	  fprintf(stderr, "for unknown reasons.\nPlease contact linux-msdos%vger.kernel.org@localhost.\n");
++	fprintf(stderr, "Set $_cpu_emu=\"full\" or \"fullsim\" to avoid this message.\n");
++      }
++      config.cpu_vm = CPUVM_EMU;
++      config.cpuemu = 4;
++      _cs = getsegment(cs);
++  }
++#endif
++
++  if (in_vm86) {
++#ifdef __i386__
++#ifdef X86_EMULATOR
++    if (config.cpu_vm != CPUVM_EMU)
++#endif
++      {
++	if (getsegment(fs) != eflags_fs_gs.fs)
++	  loadregister(fs, eflags_fs_gs.fs);
++	if (getsegment(gs) != eflags_fs_gs.gs)
++	  loadregister(gs, eflags_fs_gs.gs);
++      }
++#endif
++    return;
++  }
++
++#if SIGRETURN_WA
++  if (need_sr_wa && !DPMIValidSelector(_cs))
++    dpmi_iret_unwind(scp);
++#endif
++
++#if 0
++  /* for async signals need to restore fs/gs even if dosemu code
++   * was interrupted, because it can be interrupted in a switching
++   * routine when fs or gs are already switched but cs is not */
++  if (!DPMIValidSelector(_cs) && !async)
++    return;
++#else
++  /* as DIRECT_DPMI_SWITCH support is now removed, the above comment
++   * applies only to DPMI_iret, which is now unwound.
++   * We don't need to restore segregs for async signals any more. */
++  if (!DPMIValidSelector(_cs))
++    return;
++#endif
++
++  /* restore %fs and %gs for compatibility with NPTL. */
++  if (getsegment(fs) != eflags_fs_gs.fs)
++    loadregister(fs, eflags_fs_gs.fs);
++  if (getsegment(gs) != eflags_fs_gs.gs)
++    loadregister(gs, eflags_fs_gs.gs);
++#ifdef __x86_64__
++  loadregister(ds, eflags_fs_gs.ds);
++  loadregister(es, eflags_fs_gs.es);
++  /* kernel has the following rule: non-zero selector means 32bit base
++   * in GDT. Zero selector means 64bit base, set via msr.
++   * So if we set selector to 0, need to use also prctl(ARCH_SET_xS).
++   * Also, if the bases are not used they are 0 so no need to restore,
++   * which saves a syscall */
++  if (!eflags_fs_gs.fs && eflags_fs_gs.fsbase)
++    dosemu_arch_prctl(ARCH_SET_FS, eflags_fs_gs.fsbase);
++  if (!eflags_fs_gs.gs && eflags_fs_gs.gsbase)
++    dosemu_arch_prctl(ARCH_SET_GS, eflags_fs_gs.gsbase);
++#endif
++}
++
++SIG_PROTO_PFX
++void init_handler(struct sigcontext *scp, int async)
++{
++  /* Async signals are initially blocked.
++   * If we don't block them, nested sighandler will clobber SS
++   * before we manage to save it.
++   * Even if the nested sighandler tries hard, it can't properly
++   * restore SS, at least until the proper sigreturn() support is in.
++   * For kernels that have the proper SS support, only nonfatal
++   * async signals are initially blocked. They need to be blocked
++   * because of sas wa and because they should not interrupt
++   * deinit_handler() after it changed %fs. In this case, however,
++   * we can block them later at the right places, but this will
++   * cost a syscall per every signal.
++   * Note: in 64bit mode some segment registers are neither saved nor
++   * restored by the signal dispatching code in kernel, so we have
++   * to restore them by hands.
++   * Note: most async signals are left blocked, we unblock only few.
++   * Sync signals like SIGSEGV are never blocked.
++   */
++  __init_handler(scp, async);
++  if (!block_all_sigs)
++    return;
++#if SIGALTSTACK_WA
++  /* for SAS WA we unblock the fatal signals even later if we came
++   * from DPMI, as then we'll be switching stacks which is racy when
++   * async signals enabled. */
++  if (need_sas_wa && DPMIValidSelector(_cs))
++    return;
++#endif
++  /* either came from dosemu/vm86 or having SS_AUTODISARM -
++   * then we can unblock any signals we want. For now leave nonfatal
++   * signals blocked as they are rarely needed inside sighandlers
++   * (needed only for instremu, see
++   * https://github.com/stsp/dosemu2/issues/477
++   * ) */
++  sigprocmask(SIG_UNBLOCK, &fatal_q_mask, NULL);
++}
++
++SIG_PROTO_PFX
++void deinit_handler(struct sigcontext *scp, unsigned long *uc_flags)
++{
++  /* in fullsim mode nothing to do */
++  if (CONFIG_CPUSIM && config.cpuemu >= 4)
++    return;
++
++  if (!DPMIValidSelector(_cs))
++    return;
++
++#ifdef __x86_64__
++#ifndef UC_SIGCONTEXT_SS
++/*
++ * UC_SIGCONTEXT_SS will be set when delivering 64-bit or x32 signals on
++ * kernels that save SS in the sigcontext.  Kernels that set UC_SIGCONTEXT_SS
++ * allow signal handlers to set UC_RESTORE_SS; if UC_RESTORE_SS is set,
++ * then sigreturn will restore SS.
++ *
++ * For compatibility with old programs, the kernel will *not* set
++ * UC_RESTORE_SS when delivering signals.
++ */
++#define UC_SIGCONTEXT_SS       0x2
++#define UC_STRICT_RESTORE_SS   0x4
++#endif
++
++  if (*uc_flags & UC_SIGCONTEXT_SS) {
++    /*
++     * On Linux 4.4 (possibly) and up, the kernel can fully restore
++     * SS and ESP, so we don't need any special tricks.  To avoid confusion,
++     * force strict restore.  (Some 4.1 versions support this as well but
++     * without the uc_flags bits.  It's not trying to detect those kernels.)
++     */
++    *uc_flags |= UC_STRICT_RESTORE_SS;
++  } else {
++#if SIGRETURN_WA
++    if (!need_sr_wa) {
++      need_sr_wa = 1;
++      warn("Enabling sigreturn() work-around\n");
++    }
++    dpmi_iret_setup(scp);
++#else
++    error("Your kernel does not support UC_STRICT_RESTORE_SS and the "
++	  "work-around in dosemu is not enabled.\n");
++    leavedos_sig(11);
++#endif
++  }
++
++  if (_fs != getsegment(fs))
++    loadregister(fs, _fs);
++  if (_gs != getsegment(gs))
++    loadregister(gs, _gs);
++
++  loadregister(ds, _ds);
++  loadregister(es, _es);
++#endif
++}
++
++static int ld_sig;
++static void leavedos_call(void *arg)
++{
++  int *sig = arg;
++  leavedos(*sig);
++}
++
++int sigchld_register_handler(pid_t pid, void (*handler)(void))
++{
++  assert(chd_hndl_num < MAX_SIGCHLD_HANDLERS);
++  chld_hndl[chd_hndl_num].handler = handler;
++  chld_hndl[chd_hndl_num].pid = pid;
++  chld_hndl[chd_hndl_num].enabled = 1;
++  chd_hndl_num++;
++  return 0;
++}
++
++int sigchld_enable_handler(pid_t pid, int on)
++{
++  int i;
++  for (i = 0; i < chd_hndl_num; i++) {
++    if (chld_hndl[i].pid == pid)
++      break;
++  }
++  if (i >= chd_hndl_num)
++    return -1;
++  chld_hndl[i].enabled = on;
++  return 0;
++}
++
++static void cleanup_child(void *arg)
++{
++  int i, status;
++  pid_t pid2, pid = *(pid_t *)arg;
++
++  for (i = 0; i < chd_hndl_num; i++) {
++    if (chld_hndl[i].pid == pid)
++      break;
++  }
++  if (i >= chd_hndl_num)
++    return;
++  if (!chld_hndl[i].enabled)
++    return;
++  pid2 = waitpid(pid, &status, WNOHANG);
++  if (pid2 != pid)
++    return;
++  if (chld_hndl[i].handler)
++    chld_hndl[i].handler();
++}
++
++/* this cleaning up is necessary to avoid the port server becoming
++   a zombie process */
++static void sig_child(struct sigcontext *scp, siginfo_t *si)
++{
++  SIGNAL_save(cleanup_child, &si->si_pid, sizeof(si->si_pid), __func__);
++}
++
++int sigalrm_register_handler(void (*handler)(void))
++{
++  assert(alrm_hndl_num < MAX_SIGALRM_HANDLERS);
++  alrm_hndl[alrm_hndl_num].handler = handler;
++  alrm_hndl_num++;
++  return 0;
++}
++
++void leavedos_from_sig(int sig)
++{
++  /* anything more sophisticated? */
++  leavedos_main(sig);
++}
++
++static void leavedos_sig(int sig)
++{
++  dbug_printf("Terminating on signal %i\n", sig);
++  SIGNAL_save(leavedos_call, &sig, sizeof(sig), __func__);
++  /* abort current sighandlers */
++  if (in_handle_signals) {
++    g_printf("Interrupting active signal handlers\n");
++    in_handle_signals = 0;
++  }
++}
++
++__attribute__((noinline))
++static void _leavedos_signal(int sig, struct sigcontext *scp)
++{
++  if (ld_sig) {
++    /* don't print anything - may lock up */
++#if 0
++    error("gracefull exit failed, aborting (sig=%i)\n", sig);
++#endif
++    _exit(sig);
++  }
++  ld_sig = sig;
++  leavedos_sig(sig);
++  if (!in_vm86)
++    dpmi_sigio(scp);
++}
++
++SIG_PROTO_PFX
++static void leavedos_signal(int sig, siginfo_t *si, void *uc)
++{
++  ucontext_t *uct = uc;
++  struct sigcontext *scp = (struct sigcontext *)&uct->uc_mcontext;
++  init_handler(scp, 1);
++  _leavedos_signal(sig, scp);
++  deinit_handler(scp, &uct->uc_flags);
++}
++
++SIG_PROTO_PFX
++static void abort_signal(int sig, siginfo_t *si, void *uc)
++{
++  struct sigcontext *scp =
++	(struct sigcontext *)&((ucontext_t *)uc)->uc_mcontext;
++  init_handler(scp, 0);
++  gdb_debug();
++  _exit(sig);
++}
++
++/* Silly Interrupt Generator Initialization/Closedown */
++
++#ifdef SIG
++SillyG_t       *SillyG = 0;
++static SillyG_t SillyG_[16 + 1];
++#endif
++
++/*
++ * DANG_BEGIN_FUNCTION SIG_init
++ *
++ * description: Allow DOSEMU to be made aware when a hard interrupt occurs
++ * The IRQ numbers to monitor are taken from config.sillyint, each bit
++ * corresponding to one IRQ. The higher 16 bit are defining the use of
++ * SIGIO
++ *
++ * DANG_END_FUNCTION
++ */
++void SIG_init(void)
++{
++#if defined(SIG)
++    PRIV_SAVE_AREA
++    /* Get in touch with Silly Interrupt Handling */
++    if (config.sillyint) {
++	char            prio_table[] =
++	{8, 9, 10, 11, 12, 14, 15, 3, 4, 5, 6, 7};
++	int             i,
++	                irq;
++	SillyG_t       *sg = SillyG_;
++	for (i = 0; i < sizeof(prio_table); i++) {
++	    irq = prio_table[i];
++	    if (config.sillyint & (1 << irq)) {
++		int ret;
++		enter_priv_on();
++		ret = vm86_plus(VM86_REQUEST_IRQ, (SIGIO << 8) | irq);
++		leave_priv_setting();
++		if ( ret > 0) {
++		    g_printf("Gonna monitor the IRQ %d you requested\n", irq);
++		    sg->fd = -1;
++		    sg->irq = irq;
++		    g_printf("SIG: IRQ%d, enabling PIC-level %ld\n", irq, pic_irq_list[irq]);
++		    sg++;
++		}
++	    }
++	}
++	sg->fd = 0;
++	if (sg != SillyG_)
++	    SillyG = SillyG_;
++    }
++#endif
++}
++
++void SIG_close(void)
++{
++#if defined(SIG)
++    if (SillyG) {
++	SillyG_t       *sg = SillyG;
++	while (sg->fd) {
++	    vm86_plus(VM86_FREE_IRQ, sg->irq);
++	    sg++;
++	}
++	g_printf("Closing all IRQ you opened!\n");
++    }
++#endif
++}
++
++void sig_ctx_prepare(int tid)
++{
++  rm_stack_enter();
++  clear_IF();
++}
++
++void sig_ctx_restore(int tid)
++{
++  rm_stack_leave();
++}
++
++static void signal_thr_post(int tid)
++{
++  in_handle_signals--;
++}
++
++static void signal_thr(void *arg)
++{
++  struct SIGNAL_queue *sig = &signal_queue[SIGNAL_head];
++  struct SIGNAL_queue sig_c;	// local copy for signal-safety
++  sig_c.signal_handler = signal_queue[SIGNAL_head].signal_handler;
++  sig_c.arg_size = sig->arg_size;
++  if (sig->arg_size)
++    memcpy(sig_c.arg, sig->arg, sig->arg_size);
++  sig_c.name = sig->name;
++  SIGNAL_head = (SIGNAL_head + 1) % MAX_SIG_QUEUE_SIZE;
++  if (debug_level('g') > 5)
++    g_printf("Processing signal %s\n", sig_c.name);
++  sig_c.signal_handler(sig_c.arg);
++}
++
++static void sigstack_init(void)
++{
++#ifndef MAP_STACK
++#define MAP_STACK 0
++#endif
++
++  /* sigaltstack_wa is optional. See if we need it. */
++  stack_t dummy = { .ss_flags = SS_DISABLE | SS_AUTODISARM };
++  int err = sigaltstack(&dummy, NULL);
++#if SIGALTSTACK_WA
++  if ((err && errno == EINVAL)
++#ifdef __i386__
++      /* kernels before 4.11 had the needed functionality only for 64bits */
++      || kernel_version_code < KERNEL_VERSION(4, 11, 0)
++#endif
++     )
++  {
++    need_sas_wa = 1;
++    warn("Enabling sigaltstack() work-around\n");
++    /* for SAS WA block all signals. If we dont, there is a
++     * race that the signal can come after we switched to backup stack
++     * but before we disabled sigaltstack. We unblock the fatal signals
++     * later, only right before switching back to dosemu. */
++    block_all_sigs = 1;
++  }
++
++  if (need_sas_wa) {
++    cstack = alloc_mapping(MAPPING_SHARED, SIGSTACK_SIZE);
++    if (cstack == MAP_FAILED) {
++      error("Unable to allocate stack\n");
++      config.exitearly = 1;
++    }
++    backup_stack = alias_mapping_high(MAPPING_OTHER, SIGSTACK_SIZE,
++	PROT_READ | PROT_WRITE, cstack);
++    if (backup_stack == MAP_FAILED) {
++      error("Unable to allocate stack\n");
++      config.exitearly = 1;
++    }
++  } else {
++    cstack = mmap(NULL, SIGSTACK_SIZE, PROT_READ | PROT_WRITE,
++	MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
++    if (cstack == MAP_FAILED) {
++      error("Unable to allocate stack\n");
++      config.exitearly = 1;
++    }
++  }
++#else
++  if ((err && errno == EINVAL)
++#ifdef __i386__
++      || kernel_version_code < KERNEL_VERSION(4, 11, 0)
++#endif
++     )
++   {
++    error("Your kernel does not support SS_AUTODISARM and the "
++	  "work-around in dosemu is not enabled.\n");
++    config.exitearly = 1;
++  }
++  cstack = mmap(NULL, SIGSTACK_SIZE, PROT_READ | PROT_WRITE,
++	MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
++  if (cstack == MAP_FAILED) {
++    error("Unable to allocate stack\n");
++    config.exitearly = 1;
++  }
++#endif
++}
++
++/* DANG_BEGIN_FUNCTION signal_pre_init
++ *
++ * description:
++ *  Initialize the signals to have NONE being blocked.
++ * Currently this is NOT of much use to DOSEMU.
++ *
++ * DANG_END_FUNCTION
++ *
++ */
++void
++signal_pre_init(void)
++{
++  /* initialize user data & code selector values (used by DPMI code) */
++  /* And save %fs, %gs for NPTL */
++  eflags_fs_gs.fs = getsegment(fs);
++  eflags_fs_gs.gs = getsegment(gs);
++  eflags_fs_gs.eflags = getflags();
++  dbug_printf("initial register values: fs: 0x%04x  gs: 0x%04x eflags: 0x%04lx\n",
++    eflags_fs_gs.fs, eflags_fs_gs.gs, eflags_fs_gs.eflags);
++#ifdef __x86_64__
++  eflags_fs_gs.ds = getsegment(ds);
++  eflags_fs_gs.es = getsegment(es);
++  eflags_fs_gs.ss = getsegment(ss);
++  /* get long fs and gs bases. If they are in the first 32 bits
++     normal 386-style fs/gs switching can happen so we can ignore
++     fsbase/gsbase */
++  dosemu_arch_prctl(ARCH_GET_FS, &eflags_fs_gs.fsbase);
++  if ((unsigned long)eflags_fs_gs.fsbase <= 0xffffffff)
++    eflags_fs_gs.fsbase = 0;
++  dosemu_arch_prctl(ARCH_GET_GS, &eflags_fs_gs.gsbase);
++  if ((unsigned long)eflags_fs_gs.gsbase <= 0xffffffff)
++    eflags_fs_gs.gsbase = 0;
++  dbug_printf("initial segment bases: fs: %p  gs: %p\n",
++    eflags_fs_gs.fsbase, eflags_fs_gs.gsbase);
++#endif
++
++  /* first set up the blocking mask: registersig() and newsetqsig()
++   * adds to it */
++  sigemptyset(&q_mask);
++  sigemptyset(&nonfatal_q_mask);
++  registersig(SIGALRM, sigalrm);
++  registersig(SIGIO, sigio);
++  registersig(SIGCHLD, sig_child);
++  newsetqsig(SIGQUIT, leavedos_signal);
++  newsetqsig(SIGINT, leavedos_signal);   /* for "graceful" shutdown for ^C too*/
++  newsetqsig(SIGHUP, leavedos_signal);	/* for "graceful" shutdown */
++  newsetqsig(SIGTERM, leavedos_signal);
++  /* below ones are initialized by other subsystems */
++  registersig(SIGPROF, NULL);
++  registersig(SIG_ACQUIRE, NULL);
++  registersig(SIG_RELEASE, NULL);
++  /* mask is set up, now start using it */
++  qsig_init();
++  newsetsig(SIGILL, dosemu_fault);
++  newsetsig(SIGFPE, dosemu_fault);
++  newsetsig(SIGTRAP, dosemu_fault);
++  newsetsig(SIGBUS, dosemu_fault);
++  newsetsig(SIGABRT, abort_signal);
++  newsetsig(SIGSEGV, dosemu_fault);
++
++  /* block async signals so that threads inherit the blockage */
++  sigprocmask(SIG_BLOCK, &q_mask, NULL);
++
++  signal(SIGPIPE, SIG_IGN);
++  dosemu_pthread_self = pthread_self();
++}
++
++void
++signal_init(void)
++{
++  sigstack_init();
++#if SIGRETURN_WA
++  /* 4.6+ are able to correctly restore SS */
++  if (kernel_version_code < KERNEL_VERSION(4, 6, 0)) {
++    need_sr_wa = 1;
++    warn("Enabling sigreturn() work-around for old kernel\n");
++    /* block all sigs for SR WA. If we dont, the signal can come before
++     * SS is saved, but we can't restore SS on signal exit. */
++    block_all_sigs = 1;
++  }
++#endif
++
++  sh_tid = coopth_create("signal handling");
++  /* normally we don't need ctx handlers because the thread is detached.
++   * But some crazy code (vbe.c) can call coopth_attach() on it, so we
++   * set up the handlers just in case. */
++  coopth_set_ctx_handlers(sh_tid, sig_ctx_prepare, sig_ctx_restore);
++  coopth_set_sleep_handlers(sh_tid, handle_signals_force_enter,
++	handle_signals_force_leave);
++  coopth_set_permanent_post_handler(sh_tid, signal_thr_post);
++  coopth_set_detached(sh_tid);
++
++  event_fd = eventfd(0, EFD_CLOEXEC);
++  add_to_io_select(event_fd, async_awake, NULL);
++  rng_init(&cbks, MAX_CBKS, sizeof(struct callback_s));
++
++  /* unblock async signals in main thread */
++  pthread_sigmask(SIG_UNBLOCK, &q_mask, NULL);
++}
++
++void signal_done(void)
++{
++    struct itimerval itv;
++
++    itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0;
++    itv.it_value = itv.it_interval;
++    if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
++	g_printf("can't turn off timer at shutdown: %s\n", strerror(errno));
++    registersig(SIGALRM, NULL);
++    registersig(SIGIO, NULL);
++    registersig(SIGCHLD, NULL);
++    signal(SIGCHLD, SIG_DFL);
++    SIGNAL_head = SIGNAL_tail;
++}
++
++static void handle_signals_force_enter(int tid, int sl_state)
++{
++  if (!in_handle_signals) {
++    dosemu_error("in_handle_signals=0\n");
++    return;
++  }
++  in_handle_signals--;
++}
++
++static void handle_signals_force_leave(int tid)
++{
++  in_handle_signals++;
++}
++
++int signal_pending(void)
++{
++  return (SIGNAL_head != SIGNAL_tail);
++}
++
++/*
++ * DANG_BEGIN_FUNCTION handle_signals
++ *
++ * description:
++ *  Due to signals happening at any time, the actual work to be done
++ * because a signal occurs is done here in a serial fashion.
++ *
++ * The concept, should this eventualy work, is that a signal should only
++ * flag that it has occurred and let DOSEMU deal with it in an orderly
++ * fashion as it executes the rest of it's code.
++ *
++ * DANG_END_FUNCTION
++ *
++ */
++void handle_signals(void)
++{
++  while (signal_pending() && !in_handle_signals) {
++    in_handle_signals++;
++    coopth_start(sh_tid, signal_thr, NULL);
++    coopth_run_tid(sh_tid);
++  }
++}
++
++/* ==============================================================
++ *
++ * This is called by default at around 100Hz.
++ * (see timer_interrupt_init() in init.c)
++ *
++ * The actual formulas, starting with the configurable parameter
++ * config.freq, are:
++ *	config.freq				default=18
++ *	config.update = 1E6/config.freq		default=54945
++ *	timer tick(us) = config.update/6	default=9157.5us
++ *		       = 166667/config.freq
++ *	timer tick(Hz) = 6*config.freq		default=100Hz
++ *
++ * 6 is the magical TIMER_DIVISOR macro used to get 100Hz
++ *
++ * This call should NOT be used if you need timing accuracy - many
++ * signals can get lost e.g. when kernel accesses disk, and the whole
++ * idea of timing-by-counting is plain wrong. We'll need the Pentium
++ * counter here.
++ * ============================================================== */
++
++static void SIGALRM_call(void *arg)
++{
++  static int first = 0;
++  static hitimer_t cnt200 = 0;
++  static hitimer_t cnt1000 = 0;
++  int i;
++
++  if (first==0) {
++    cnt200 =
++    cnt1000 =
++    pic_sys_time;	/* initialize */
++    first = 1;
++  }
++
++  if (video_initialized && !config.vga)
++    update_screen();
++
++  for (i = 0; i < alrm_hndl_num; i++)
++    alrm_hndl[i].handler();
++
++  if (config.rdtsc)
++    update_cputime_TSCBase();
++  timer_tick();
++
++#if 0
++/*
++ * DANG_BEGIN_REMARK
++ *  Check for keyboard coming from client
++ *  For now, first byte is interrupt requests from Client
++ * DANG_END_REMARK
++ */
++ if (*(u_char *)(shared_qf_memory + CLIENT_REQUEST_FLAG_AREA) & 0x40) {
++   k_printf("KBD: Client sent key\n");
++   pic_request (PIC_IRQ1);
++   *(u_char *)(shared_qf_memory + CLIENT_REQUEST_FLAG_AREA) &=  ~0x40;
++ }
++#endif
++
++  io_select();	/* we need this in order to catch lost SIGIOs */
++  /* catch user hooks here */
++  if (uhook_fdin != -1) uhook_poll();
++
++  alarm_idle();
++
++  /* Here we 'type in' prestrokes from commandline, as long as there are any
++   * Were won't overkill dosemu, hence we type at a speed of 14cps
++   */
++  if (config.pre_stroke) {
++    static int count=-1;
++    if (--count < 0) {
++      count = type_in_pre_strokes();
++      if (count <0) count =7; /* with HZ=100 we have a stroke rate of 14cps */
++    }
++  }
++
++  /* this should be for per-second activities, it is actually at
++   * 200ms more or less (PARTIALS=5) */
++  if ((pic_sys_time-cnt200) >= (PIT_TICK_RATE/PARTIALS)) {
++    cnt200 = pic_sys_time;
++/*    g_printf("**** ALRM: %dms\n",(1000/PARTIALS)); */
++
++    printer_tick(0);
++    floppy_tick();
++  }
++
++/* We update the RTC from here if it has not been defined as a thread */
++
++  /* this is for EXACT per-second activities (can produce bursts) */
++  if ((pic_sys_time-cnt1000) >= PIT_TICK_RATE) {
++    cnt1000 += PIT_TICK_RATE;
++/*    g_printf("**** ALRM: 1sec\n"); */
++    rtc_update();
++  }
++}
++
++/* DANG_BEGIN_FUNCTION SIGNAL_save
++ *
++ * arguments:
++ * context     - signal context to save.
++ * signal_call - signal handling routine to be called.
++ *
++ * description:
++ *  Save into an array structure queue the signal context of the current
++ * signal as well as the function to call for dealing with this signal.
++ * This is a queue because any signal may occur multiple times before
++ * DOSEMU deals with it down the road.
++ *
++ * DANG_END_FUNCTION
++ *
++ */
++void SIGNAL_save(void (*signal_call)(void *), void *arg, size_t len,
++	const char *name)
++{
++  signal_queue[SIGNAL_tail].signal_handler = signal_call;
++  signal_queue[SIGNAL_tail].arg_size = len;
++  assert(len <= MAX_SIG_DATA_SIZE);
++  if (len)
++    memcpy(signal_queue[SIGNAL_tail].arg, arg, len);
++  signal_queue[SIGNAL_tail].name = name;
++  SIGNAL_tail = (SIGNAL_tail + 1) % MAX_SIG_QUEUE_SIZE;
++  if (in_dpmi_pm())
++    dpmi_return_request();
++}
++
++
++/*
++ * DANG_BEGIN_FUNCTION SIGIO_call
++ *
++ * description:
++ *  Whenever I/O occurs on devices allowing SIGIO to occur, DOSEMU
++ * will be flagged to run this call which inturn checks which
++ * fd(s) was set and execute the proper routine to get the I/O
++ * from that device.
++ *
++ * DANG_END_FUNCTION
++ *
++ */
++static void SIGIO_call(void *arg){
++  /* Call select to see if any I/O is ready on devices */
++  io_select();
++}
++
++#ifdef __linux__
++static void sigio(struct sigcontext *scp, siginfo_t *si)
++{
++  /* prints non reentrant! dont do! */
++#if 0
++  g_printf("got SIGIO\n");
++#endif
++  e_gen_sigalrm(scp);
++  SIGNAL_save(SIGIO_call, NULL, 0, __func__);
++  if (!in_vm86)
++    dpmi_sigio(scp);
++}
++
++static void sigalrm(struct sigcontext *scp, siginfo_t *si)
++{
++  if(e_gen_sigalrm(scp)) {
++    SIGNAL_save(SIGALRM_call, NULL, 0, __func__);
++    if (!in_vm86)
++      dpmi_sigio(scp);
++  }
++}
++
++__attribute__((noinline))
++static void sigasync0(int sig, struct sigcontext *scp, siginfo_t *si)
++{
++  pthread_t tid = pthread_self();
++  if (!pthread_equal(tid, dosemu_pthread_self)) {
++    char name[128];
++    pthread_getname_np(tid, name, sizeof(name));
++    dosemu_error("Async signal %i from thread %s\n", sig, name);
++  }
++  if (sighandlers[sig])
++	  sighandlers[sig](scp, si);
++}
++
++SIG_PROTO_PFX
++static void sigasync(int sig, siginfo_t *si, void *uc)
++{
++  ucontext_t *uct = uc;
++  struct sigcontext *scp = (struct sigcontext *)&uct->uc_mcontext;
++  init_handler(scp, 1);
++  sigasync0(sig, scp, si);
++  deinit_handler(scp, &uct->uc_flags);
++}
++#endif
++
++
++void do_periodic_stuff(void)
++{
++    check_leavedos();
++    handle_signals();
++#ifdef USE_MHPDBG
++    /* mhp_debug() must be called exactly after handle_signals()
++     * and before coopth_run(). handle_signals() feeds input to
++     * debugger, and coopth_run() runs DPMI (oops!). We need to
++     * run debugger before DPMI to not lose single-steps. */
++    if (mhpdbg.active)
++	mhp_debug(DBG_POLL, 0, 0);
++#endif
++    coopth_run();
++
++    if (video_initialized && Video && Video->change_config)
++	update_xtitle();
++}
++
++void add_thread_callback(void (*cb)(void *), void *arg, const char *name)
++{
++  if (cb) {
++    struct callback_s cbk;
++    int i;
++    cbk.func = cb;
++    cbk.arg = arg;
++    cbk.name = name;
++    pthread_mutex_lock(&cbk_mtx);
++    i = rng_put(&cbks, &cbk);
++    g_printf("callback %s added, %i queued\n", name, rng_count(&cbks));
++    pthread_mutex_unlock(&cbk_mtx);
++    if (!i)
++      error("callback queue overflow, %s\n", name);
++  }
++  eventfd_write(event_fd, 1);
++  /* unfortunately eventfd does not support SIGIO :( So we kill ourself. */
++  pthread_kill(dosemu_pthread_self, SIGIO);
++}
++
++static void async_awake(void *arg)
++{
++  struct callback_s cbk;
++  int i;
++  eventfd_t val;
++  eventfd_read(event_fd, &val);
++  g_printf("processing %"PRId64" callbacks\n", val);
++  do {
++    pthread_mutex_lock(&cbk_mtx);
++    i = rng_get(&cbks, &cbk);
++    pthread_mutex_unlock(&cbk_mtx);
++    if (i)
++      cbk.func(cbk.arg);
++  } while (i);
++}
++
++static int saved_fc;
++
++void signal_switch_to_dosemu(void)
++{
++  saved_fc = fault_cnt;
++  fault_cnt = 0;
++}
++
++void signal_switch_to_dpmi(void)
++{
++  fault_cnt = saved_fc;
++}
++
++#if SIGALTSTACK_WA
++static void signal_sas_wa(void)
++{
++  int err;
++  stack_t ss = {};
++  m_ucontext_t hack;
++  unsigned char *sp;
++  unsigned char *top = cstack + SIGSTACK_SIZE;
++  unsigned char *btop = backup_stack + SIGSTACK_SIZE;
++  ptrdiff_t delta;
++
++  if (getmcontext(&hack) == 0) {
++    sp = alloca(sizeof(void *));
++    delta = top - sp;
++    asm volatile(
++#ifdef __x86_64__
++    "mov %0, %%rsp\n"
++#else
++    "mov %0, %%esp\n"
++#endif
++     :: "r"(btop - delta) : "sp");
++  } else {
++    sigprocmask(SIG_UNBLOCK, &fatal_q_mask, NULL);
++    return;
++  }
++
++  ss.ss_flags = SS_DISABLE;
++  /* sas will re-enable itself when returning from sighandler */
++  err = sigaltstack(&ss, NULL);
++  if (err)
++    perror("sigaltstack");
++
++  setmcontext(&hack);
++}
++#endif
++
++void signal_return_to_dosemu(void)
++{
++#if SIGALTSTACK_WA
++  if (need_sas_wa)
++    signal_sas_wa();
++#endif
++}
++
++void signal_return_to_dpmi(void)
++{
++}
++
++void signal_set_altstack(int on)
++{
++  stack_t stk;
++
++  if (!on) {
++    stk.ss_sp = NULL;
++    stk.ss_size = 0;
++    stk.ss_flags = SS_DISABLE;
++  } else {
++    stk.ss_sp = cstack;
++    stk.ss_size = SIGSTACK_SIZE;
++#if SIGALTSTACK_WA
++    stk.ss_flags = SS_ONSTACK | (need_sas_wa ? 0 : SS_AUTODISARM);
++#else
++    stk.ss_flags = SS_ONSTACK | SS_AUTODISARM;
++#endif
++  }
++  sigaltstack(&stk, NULL);
++}
++
++void signal_unblock_async_sigs(void)
++{
++  /* unblock only nonfatal, fatals should already be unblocked */
++  sigprocmask(SIG_UNBLOCK, &nonfatal_q_mask, NULL);
++}
++
++void signal_restore_async_sigs(void)
++{
++  /* block sigs even for !sas_wa because if deinit_handler is
++   * interrupted after changing %fs, we are in troubles */
++  sigprocmask(SIG_BLOCK, &nonfatal_q_mask, NULL);
++}
diff --git a/dosemu2/patches/patch-src_arch_netbsd_async_sigsegv.c b/dosemu2/patches/patch-src_arch_netbsd_async_sigsegv.c
new file mode 100644
index 0000000000..1de43b3e15
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_async_sigsegv.c
@@ -0,0 +1,508 @@
+$NetBSD$
+
+--- src/arch/netbsd/async/sigsegv.c.orig	2017-11-02 06:34:33.816314870 +0000
++++ src/arch/netbsd/async/sigsegv.c
+@@ -0,0 +1,503 @@
++#include "config.h"
++#include "mhpdbg.h"
++#include "debug.h"
++
++/* Define if we want graphics in X (of course we want :-) (root@zaphod) */
++/* WARNING: This may not work in BSD, because it was written for Linux! */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <signal.h>
++#include <unistd.h>
++#include <pthread.h>
++#include <linux/version.h>
++
++#include "emu.h"
++#include "utilities.h"
++#include "int.h"
++
++#include "video.h"
++#include "vgaemu.h" /* root@zaphod */
++
++#include "dpmi.h"
++#include "cpu-emu.h"
++#include "dosemu_config.h"
++#include "sig.h"
++
++/* Function prototypes */
++void print_exception_info(struct sigcontext *scp);
++
++
++/*
++ * All of the functions in this module need to be declared with
++ *   __attribute__((no_instrument_function))
++ * so that they can safely handle signals that occur in DPMI context when
++ * DOSEMU is built with the "-pg" gcc flag (which enables instrumentation for
++ * gprof profiling).
++ *
++ * The reason for this is that mcount(), implicitly called from functions
++ * instrumented with "-pg", requires access to thread-local state, and on x86,
++ * TLS is implemented using the GS to refer to a segment in which the
++ * thread-local variables are stored.
++ *
++ * However, in DPMI context, GS does not refer to this segment, and the kernel
++ * does not (cannot?) restore it to do so when it invokes a signal handler, so
++ * we must prevent mcount() from being called at all in this context.
++ */
++
++
++/*
++ * DANG_BEGIN_FUNCTION dosemu_fault(int, struct sigcontext);
++ *
++ * All CPU exceptions (except 13=general_protection from V86 mode,
++ * which is directly scanned by the kernel) are handled here.
++ *
++ * DANG_END_FUNCTION
++ */
++static int dosemu_fault1(int signal, struct sigcontext *scp)
++{
++  if (fault_cnt > 1) {
++    error("Fault handler re-entered! signal=%i _trapno=0x%X\n",
++      signal, _trapno);
++    if (!in_vm86 && !DPMIValidSelector(_cs)) {
++      gdb_debug();
++      _exit(43);
++    } else {
++      error("BUG: Fault handler re-entered not within dosemu code! in_vm86=%i\n",
++        in_vm86);
++    }
++    goto bad;
++  }
++#ifdef __x86_64__
++  if (_trapno == 0x0e && _cr2 > 0xffffffff)
++  {
++    dosemu_error("Accessing reserved memory at %08lx\n"
++	  "\tMaybe a null segment register\n",_cr2);
++    goto bad;
++  }
++#endif
++
++
++  if (in_vm86) {
++    if (_trapno == 0x0e) {
++#ifdef X86_EMULATOR
++      if (config.cpuemu > 1) {
++        if (e_emu_pagefault(scp, 0))
++          return 0;
++        if (!CONFIG_CPUSIM && e_handle_pagefault(scp)) {
++          dosemu_error("touched jit-protected page in vm86-emu\n");
++          return 0;
++        }
++        goto bad;
++      }
++#endif
++      /* we can get to instremu from here, so unblock SIGALRM & friends.
++       * It is needed to interrupt instremu when it runs for too long. */
++      signal_unblock_async_sigs();
++      if (vga_emu_fault(scp, 0) == True)
++        return 0;
++    }
++    /* cpu-emu may decide to call vm86_fault() later */
++    if (!CONFIG_CPUSIM && config.cpuemu > 1 && e_handle_fault(scp))
++      return 0;
++    return vm86_fault(scp);
++  }
++
++  /* At first let's find out where we came from */
++  if (!DPMIValidSelector(_cs)) {
++#ifdef X86_EMULATOR
++    /* Possibilities:
++     * 1. Compiled code touches VGA prot
++     * 2. Compiled code touches cpuemu prot
++     * 3. Compiled code touches DPMI prot
++     * 4. fullsim code touches DPMI prot
++     * 5. dosemu code touches cpuemu prot (bug)
++     * Compiled code means dpmi-jit, otherwise vm86 not here.
++     */
++    if (_trapno == 0x0e && config.cpuemu > 1) {
++      /* cases 1, 2, 3, 4 */
++      if (config.cpuemu >= 4 && e_emu_pagefault(scp, 1))
++        return 0;
++      /* case 5, any jit, bug */
++      if (!CONFIG_CPUSIM && e_handle_pagefault(scp)) {
++        dosemu_error("touched jit-protected page\n");
++        return 0;
++      }
++    }
++    /* compiled code can cause fault (usually DE, Divide Exception) */
++    if (!CONFIG_CPUSIM && config.cpuemu >= 4 && e_handle_fault(scp))
++      return 0;
++#endif
++    error("Fault in dosemu code, in_dpmi=%i\n", dpmi_active());
++    /* TODO - we can start gdb here */
++    /* start_gdb() */
++    /* Going to die from here */
++    goto bad;	/* well, this goto is unnecessary but I like gotos:) */
++  } else {
++    if (_trapno == 0x0e) {
++      int rc;
++#ifdef HOST_ARCH_X86
++     /* DPMI code touches cpuemu prot */
++      if (config.cpuemu > 1 && !CONFIG_CPUSIM && e_handle_pagefault(scp))
++        return 1;
++#endif
++      signal_unblock_async_sigs();
++      rc = vga_emu_fault(scp, 1);
++      /* going for dpmi_fault() or deinit_handler(),
++       * careful with async signals and sas_wa */
++      signal_restore_async_sigs();
++      if (rc == True)
++        return dpmi_check_return(scp);
++    }
++    /* Not in dosemu code: dpmi_fault() will handle that */
++    return dpmi_fault(scp);
++  }
++
++bad:
++/* All recovery attempts failed, going to die :( */
++
++  {
++#ifdef __x86_64__
++    unsigned char *fsbase, *gsbase;
++#endif
++    error("cpu exception in dosemu code outside of %s!\n"
++	  "trapno: 0x%02x  errorcode: 0x%08lx  cr2: 0x%08lx\n"
++	  "eip: 0x%08lx  esp: 0x%08lx  eflags: 0x%08lx\n"
++	  "cs: 0x%04x  ds: 0x%04x  es: 0x%04x  ss: 0x%04x\n"
++	  "fs: 0x%04x  gs: 0x%04x\n",
++	  (in_dpmi_pm() ? "DPMI client" : "VM86()"),
++	  _trapno, _err, _cr2,
++	  _rip, _rsp, _eflags, _cs, _ds, _es, _ss, _fs, _gs);
++#ifdef __x86_64__
++    dosemu_arch_prctl(ARCH_GET_FS, &fsbase);
++    dosemu_arch_prctl(ARCH_GET_GS, &gsbase);
++    error("@fsbase: %p gsbase: %p\n", fsbase, gsbase);
++#endif
++    error("@\n");
++
++    error("Please install gdb, update dosemu from git, compile it with debug\n"
++        "info and report with the contents of ~/.dosemu/boot.log at\n"
++"https://github.com/stsp/dosemu2/issues\n\n";
++);
++    gdb_debug();
++
++    if (DPMIValidSelector(_cs))
++      print_exception_info(scp);
++    if (in_vm86)
++	show_regs();
++    fatalerr = 4;
++    leavedos_main(fatalerr);		/* shouldn't return */
++    return 0;
++  }
++}
++
++/* noinline is to prevent gcc from moving TLS access around init_handler() */
++__attribute__((noinline))
++static void dosemu_fault0(int signal, struct sigcontext *scp)
++{
++  pthread_t tid;
++
++  if (fault_cnt > 2) {
++   /*
++    * At this point we already tried leavedos(). Now try _exit()
++    * and NOT exit(3), because glibc is probably malfunctions if
++    * we are here.
++    */
++    _exit(255);
++  }
++
++  tid = pthread_self();
++  if (!pthread_equal(tid, dosemu_pthread_self)) {
++    char name[128];
++
++    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
++    pthread_getname_np(tid, name, sizeof(name));
++    dosemu_error("thread %s got signal %i\n", name, signal);
++    _exit(23);
++    return;
++  }
++
++  if (kernel_version_code < KERNEL_VERSION(2, 6, 14)) {
++    sigset_t set;
++
++    /* this emulates SA_NODEFER, so that we can double fault.
++       SA_NODEFER only works as documented in Linux kernels >= 2.6.14.
++    */
++    sigemptyset(&set);
++    sigaddset(&set, signal);
++    sigprocmask(SIG_UNBLOCK, &set, NULL);
++  }
++
++  if (debug_level('g')>7)
++    g_printf("Entering fault handler, signal=%i _trapno=0x%X\n",
++      signal, _trapno);
++
++  dosemu_fault1(signal, scp);
++
++  if (debug_level('g')>8)
++    g_printf("Returning from the fault handler\n");
++}
++
++#ifdef __linux__
++SIG_PROTO_PFX
++void dosemu_fault(int signal, siginfo_t *si, void *uc)
++{
++  ucontext_t *uct = uc;
++  struct sigcontext *scp = (struct sigcontext *)&uct->uc_mcontext;
++  /* need to call init_handler() before any syscall.
++   * Additionally, TLS access should be done in a separate no-inline
++   * function, so that gcc not to move the TLS access around init_handler(). */
++  init_handler(scp, 0);
++  fault_cnt++;
++  dosemu_fault0(signal, scp);
++  fault_cnt--;
++  deinit_handler(scp, &uct->uc_flags);
++}
++#endif /* __linux__ */
++
++/*
++ * DANG_BEGIN_FUNCTION print_exception_info
++ *
++ * Prints information about an exception: exception number, error code,
++ * address, reason, etc.
++ *
++ * DANG_END_FUNCTION
++ *
++ */
++void print_exception_info(struct sigcontext *scp)
++{
++  int i;
++
++  switch(_trapno)
++    {
++    case 0:
++      error("@Division by zero\n");
++      break;
++
++
++    case 1:
++      error("@Debug exception\n");
++      break;
++
++
++    case 3:
++      error("@Breakpoint exception (caused by INT 3 instruction)\n");
++      break;
++
++
++    case 4:
++      error("@Overflow exception (caused by INTO instruction)\n");
++      break;
++
++
++    case 5:
++      error("@Bound exception (caused by BOUND instruction)\n");
++      break;
++
++
++    case 6: {
++      unsigned char *csp;
++      int ps = getpagesize();
++      unsigned pa = _rip & (ps - 1);
++      int sub = min(pa, 10);
++      int sup = min(ps - pa, 10);
++      error("@Invalid opcode\n");
++      error("@Opcodes: ");
++      csp = (unsigned char *) _rip - sub;
++      for (i = 0; i < 10 - sub; i++)
++        error("@XX ");
++      for (i = 0; i < sub; i++)
++	error("@%02x ", *csp++);
++      error("@-> ");
++      for (i = 0; i < sup; i++)
++	error("@%02x ", *csp++);
++      for (i = 0; i < 10 - sup; i++)
++        error("@XX ");
++      error("@\n");
++      break;
++    }
++
++    case 7:
++      error("@Coprocessor exception (coprocessor not available)\n");
++      /* I'd like to print some info on the EM, MP, and TS flags in CR0,
++       * but I don't know where I can get that information :-(
++       * Anyway, this exception should not happen... (Erik Mouw)
++       */
++      break;
++
++
++    case 8:
++      error("@Double fault\n");
++      break;
++
++
++    case 9:
++      error("@Coprocessor segment overflow\n");
++      break;
++
++
++    case 0xa:
++      error("@Invalid TSS\n");
++      if(_err & 0x02)
++	error("@IDT");
++      else if(_err & 0x04)
++	error("@LDT");
++      else
++	error("@GDT");
++
++      error("@ selector: 0x%04lx\n", ((_err >> 3) & 0x1fff ));
++
++      if(_err & 0x01)
++	error("@Exception was not caused by DOSEMU\n");
++      else
++	error("@Exception was caused by DOSEMU\n");
++      break;
++
++
++    case 0xb:
++      error("@Segment not available\n");
++      /* This is the same code as case 0x0a; the compiler merges these
++       * blocks, so I don't have to edit some dirty constructions to
++       * generate one block of code. (Erik Mouw)
++       */
++      if(_err & 0x02)
++	error("@IDT");
++      else if(_err & 0x04)
++	error("@LDT");
++      else
++	error("@GDT");
++
++      error("@ selector: 0x%04lx\n", ((_err >> 3) & 0x1fff ));
++
++      if(_err & 0x01)
++	error("@Exception was not caused by DOSEMU\n");
++      else
++	error("@Exception was caused by DOSEMU\n");
++      break;
++
++
++    case 0xc:
++      error("@Stack exception\n");
++      break;
++
++
++    case 0xd:
++      error("@General protection exception\n");
++      /* This is the same code as case 0x0a; the compiler merges these
++       * blocks, so I don't have to edit some dirty constructions to
++       * generate one block of code. (Erik Mouw)
++       */
++      if(_err & 0x02)
++	error("@IDT");
++      else if(_err & 0x04)
++	error("@LDT");
++      else
++	error("@GDT");
++
++      error("@ selector: 0x%04lx\n", ((_err >> 3) & 0x1fff ));
++
++      if(_err & 0x01)
++	error("@Exception was not caused by DOSEMU\n");
++      else
++	error("@Exception was caused by DOSEMU\n");
++      break;
++
++
++    case 0xe:
++      error("@Page fault: ");
++      if(_err & 0x02)
++	error("@write");
++      else
++	error("@read");
++
++      error("@ instruction to linear address: 0x%08lx\n", _cr2);
++
++      error("@CPU was in ");
++      if(_err & 0x04)
++	error("@user mode\n");
++      else
++	error("@supervisor mode\n");
++
++      error("@Exception was caused by ");
++      if(_err & 0x01)
++	error("@insufficient privilege\n");
++      else
++	error("@non-available page\n");
++      break;
++
++   case 0x10: {
++      int i, n;
++      unsigned short sw;
++#ifdef __x86_64__
++      fpregset_t p = ((mcontext_t *)scp)->fpregs;
++      error ("@Coprocessor Error:\n");
++      error ("@cwd=%04x swd=%04x ftw=%04x\n", p->cwd, p->swd, p->ftw);
++      error ("@cs:rip=%04x:%08lx ds:data=%04x:%08lx\n",	_cs,p->rip,_ds,p->rdp);
++      sw = p->swd;
++#else
++      struct _fpstate *p = scp->fpstate;
++      error ("@Coprocessor Error:\n");
++      error ("@cw=%04x sw=%04x tag=%04x\n",
++	     ((unsigned short)(p->cw)),((unsigned short)(p->sw)),
++	((unsigned short)(p->tag)));
++      error ("@cs:eip=%04x:%08x ds:data=%04x:%08x\n",
++	     ((unsigned short)(p->cssel)),(unsigned)p->ipoff,
++	     ((unsigned short)(p->datasel)),(unsigned)p->dataoff);
++      sw = p->sw;
++#endif
++      if ((sw&0x80)==0) error("@No error summary bit,why?\n");
++      else {
++	if (sw&0x20) error("@Precision\n");
++	if (sw&0x10) error("@Underflow\n");
++	if (sw&0x08) error("@Overflow\n");
++	if (sw&0x04) error("@Divide by 0\n");
++	if (sw&0x02) error("@Denormalized\n");
++	if ((sw&0x41)==0x01) error("@Invalid op\n");
++	  else if ((sw&0x41)==0x41) error("@Stack fault\n");
++      }
++      n = (sw >> 11) & 7;
++      for (i=0; i<8; i++) {
++	unsigned short *r = p->_st[i].significand;
++	unsigned short e = p->_st[i].exponent;
++	error ("@fpr[%d] = %04x:%04x%04x%04x%04x\n",n,e,r[3],r[2],r[1],r[0]);
++	n = (n+1) & 7;
++      }
++      } break;
++
++#ifdef __SSE__
++   case 0x13: {
++      int i;
++      unsigned mxcsr;
++#ifdef __x86_64__
++      fpregset_t p = ((mcontext_t *)scp)->fpregs;
++      error ("@SIMD Floating-Point Exception:\n");
++      mxcsr = p->mxcsr;
++      error ("@mxcsr=%08x, mxcr_mask=%08x\n",mxcsr,(unsigned)(p->mxcr_mask));
++#else
++      struct _fpstate *p = scp->fpstate;
++      error ("@SIMD Floating-Point Exception:\n");
++      mxcsr = p->mxcsr;
++      error ("@mxcsr=%08x\n",mxcsr);
++#endif
++      if (mxcsr&0x40) error("@Denormals are zero\n");
++      if (mxcsr&0x20) error("@Precision\n");
++      if (mxcsr&0x10) error("@Underflow\n");
++      if (mxcsr&0x08) error("@Overflow\n");
++      if (mxcsr&0x04) error("@Divide by 0\n");
++      if (mxcsr&0x02) error("@Denormalized\n");
++      if (mxcsr&0x01) error("@Invalid op\n");
++      for (i=0; i<sizeof(p->_xmm)/sizeof(p->_xmm[0]); i++)
++      {
++	error ("@xmm[%d] = %08x:%08x:%08x:%08x\n",i,
++	      (unsigned)p->_xmm[i].element[0], (unsigned)p->_xmm[i].element[1],
++	      (unsigned)p->_xmm[i].element[2], (unsigned)p->_xmm[i].element[3]);
++      }
++    } break;
++#endif
++
++    default:
++      error("@Unknown exception\n");
++      break;
++    }
++}
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mapping_Makefile b/dosemu2/patches/patch-src_arch_netbsd_mapping_Makefile
new file mode 100644
index 0000000000..279afc491c
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mapping_Makefile
@@ -0,0 +1,35 @@
+$NetBSD$
+
+--- src/arch/netbsd/mapping/Makefile.orig	2017-11-02 06:34:44.091795113 +0000
++++ src/arch/netbsd/mapping/Makefile
+@@ -0,0 +1,30 @@
++#
++# (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team".
++#
++# for details see file COPYING in the DOSEMU distribution
++#
++
++top_builddir=../../../..
++include $(top_builddir)/Makefile.conf
++
++# This is the Makefile for the mapping-subdirectory of DOSEMU.
++# Please send comments and bug-reports to Hans Lermen <lermen%fgan.de@localhost>
++
++
++#The C files, include files and dependancies here.
++CFILES = mapping.c mapshm.c mapfile.c
++DEPENDS = $(CFILES:.c=.d)
++HFILES =
++
++
++# Insert all source- and header-files here.
++ALL = $(CFILES) $(HFILES)
++
++# All object-files are included here.
++OBJS = $(CFILES:.c=.o)
++
++all: lib
++
++install:
++
++include $(REALTOPDIR)/src/Makefile.common
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.c b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.c
new file mode 100644
index 0000000000..2b4a734bc9
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.c
@@ -0,0 +1,304 @@
+$NetBSD$
+
+--- src/arch/netbsd/mapping/mapfile.c.orig	2017-11-02 06:34:44.092669600 +0000
++++ src/arch/netbsd/mapping/mapfile.c
+@@ -0,0 +1,299 @@
++/*
++ * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team".
++ *
++ * for details see file COPYING in the DOSEMU distribution
++ */
++
++/*
++ * Purpose: memory mapping library, posix SHM and file backends.
++ *
++ * Authors: Stas Sergeev, Bart Oldeman.
++ * Initially started by Hans Lermen, old copyrights below:
++ */
++/* file mapfile.c
++ * file mapping driver
++ *	Hans Lermen, lermen%fgan.de@localhost
++ */
++
++#include "config.h"
++#include <unistd.h>
++#include <string.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <assert.h>
++#include <sys/mman.h>
++
++
++#include "emu.h"
++#include "mapping.h"
++#include "smalloc.h"
++#include "utilities.h"
++
++/* ------------------------------------------------------------ */
++
++static smpool pgmpool;
++static int mpool_numpages = (32 * 1024) / 4;
++static char *mpool = 0;
++
++static int tmpfile_fd = -1;
++
++static void *alias_mapping_file(int cap, void *target, size_t mapsize, int protect, void *source)
++{
++  int fixed = 0;
++  off_t offs = (char *)source - mpool;
++  void *addr;
++
++  if (offs < 0 || (offs+mapsize >= (mpool_numpages*PAGE_SIZE))) {
++    Q_printf("MAPPING: alias_map to address outside of temp file\n");
++    errno = EINVAL;
++    return MAP_FAILED;
++  }
++  if (target != (void *)-1)
++    fixed = MAP_FIXED;
++  else
++    target = NULL;
++  addr =  mmap(target, mapsize, protect, MAP_SHARED | fixed, tmpfile_fd, offs);
++  if (addr == MAP_FAILED) {
++    addr =  mmap(target, mapsize, protect & ~PROT_EXEC, MAP_SHARED | fixed,
++		 tmpfile_fd, offs);
++    if (addr != MAP_FAILED)
++      mprotect(addr, mapsize, protect);
++  }
++#if 1
++  Q_printf("MAPPING: alias_map, fileoffs %llx to %p size %zx, result %p\n",
++			(long long)offs, target, mapsize, addr);
++#endif
++  return addr;
++}
++
++static void discardtempfile(void)
++{
++  close(tmpfile_fd);
++  tmpfile_fd = -1;
++}
++
++static int open_mapping_f(int cap)
++{
++    int mapsize, estsize, padsize;
++
++    if (cap) Q_printf("MAPPING: open, cap=%s\n",
++	  decode_mapping_cap(cap));
++
++    padsize = 4*1024;
++
++    /* first estimate the needed size of the mapfile */
++    mapsize  = HMASIZE >> 10;	/* HMA */
++ 				/* VGAEMU */
++    mapsize += config.vgaemu_memsize ? config.vgaemu_memsize : 1024;
++    mapsize += config.ems_size;	/* EMS */
++    mapsize += LOWMEM_SIZE >> 10; /* Low Mem */
++    estsize = mapsize;
++				/* keep heap fragmentation in mind */
++    mapsize += (mapsize/4 < padsize ? padsize : mapsize/4);
++    mpool_numpages = mapsize / 4;
++    mapsize = mpool_numpages * PAGE_SIZE; /* make sure we are page aligned */
++
++    ftruncate(tmpfile_fd, 0);
++    if (ftruncate(tmpfile_fd, mapsize) == -1) {
++      if (!cap)
++	error("MAPPING: cannot size temp file pool, %s\n",strerror(errno));
++      discardtempfile();
++      if (!cap)return 0;
++      leavedos(2);
++    }
++    /* /dev/shm may be mounted noexec, and then mounting PROT_EXEC fails.
++       However mprotect may work around this (maybe not in future kernels)
++    */
++    mpool = mmap(0, mapsize, PROT_READ|PROT_WRITE,
++    		MAP_SHARED, tmpfile_fd, 0);
++    if (mpool == MAP_FAILED ||
++	mprotect(mpool, mapsize, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
++      char *err = strerror(errno);
++      char s[] = "MAPPING: cannot size temp file pool, %s\n";
++      discardtempfile();
++      if (!cap) {
++	Q_printf(s,err);
++	return 0;
++      }
++      leavedos(2);
++    }
++    /* the memory pool itself can just be rw though */
++    mprotect(mpool, mapsize, PROT_READ|PROT_WRITE);
++    Q_printf("MAPPING: open, mpool (min %dK) is %d Kbytes at %p-%p\n",
++		estsize, mapsize/1024, mpool, mpool+mapsize-1);
++    sminit(&pgmpool, mpool, mapsize);
++
++  /*
++   * 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 int open_mapping_file(int cap)
++{
++  if (tmpfile_fd < 0) {
++    tmpfile_fd = fileno(tmpfile());
++    open_mapping_f(cap);
++  }
++  return 1;
++}
++
++#ifdef HAVE_SHM_OPEN
++static int open_mapping_pshm(int cap)
++{
++  char *name;
++  int ret;
++
++  if (tmpfile_fd < 0) {
++    ret = asprintf(&name, "%s%d", "dosemu_", getpid());
++    assert(ret != -1);
++
++    tmpfile_fd = shm_open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
++    if (tmpfile_fd == -1) {
++      free(name);
++      return 0;
++    }
++    shm_unlink(name);
++    free(name);
++    if (!open_mapping_f(cap))
++      return 0;
++  }
++  return 1;
++}
++#endif
++
++static void close_mapping_file(int cap)
++{
++  Q_printf("MAPPING: close, cap=%s\n", decode_mapping_cap(cap));
++  if (cap == MAPPING_ALL && tmpfile_fd != -1) discardtempfile();
++}
++
++static void *alloc_mapping_file(int cap, size_t mapsize)
++{
++  Q__printf("MAPPING: alloc, cap=%s, mapsize=%zx\n", cap, mapsize);
++  return smalloc(&pgmpool, mapsize);
++}
++
++static void free_mapping_file(int cap, void *addr, size_t mapsize)
++/* NOTE: addr needs to be the same as what was supplied by alloc_mapping_file */
++{
++  Q__printf("MAPPING: free, cap=%s, addr=%p, mapsize=%zx\n",
++	cap, addr, mapsize);
++  smfree(&pgmpool, addr);
++}
++
++/*
++ * NOTE: DPMI relies on realloc_mapping() _not_ changing the address ('addr'),
++ *       when shrinking the memory region.
++ */
++static void *realloc_mapping_file(int cap, void *addr, size_t oldsize, size_t newsize)
++{
++  Q__printf("MAPPING: realloc, cap=%s, addr=%p, oldsize=%zx, newsize=%zx\n",
++	cap, addr, oldsize, newsize);
++  if (cap & (MAPPING_EMS | MAPPING_DPMI)) {
++    int size = smget_area_size(&pgmpool, addr);
++    void *addr_;
++
++    if (!size || size != oldsize) return (void *)-1;
++    if (size == newsize) return addr;
++		/* NOTE: smrealloc() does not change addr,
++		 *       when shrinking the memory region.
++		 */
++    addr_ = smrealloc(&pgmpool, addr, newsize);
++    if (!addr_) {
++      Q_printf("MAPPING: pgrealloc(0x%p,0x%zx,) failed\n",
++		addr, newsize);
++      return (void *)-1;
++    }
++    return addr_;
++  }
++  return (void *)-1;
++}
++
++static int munmap_mapping_file(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);
++}
++
++#ifdef HAVE_SHM_OPEN
++struct mappingdrivers mappingdriver_shm = {
++  "mapshm",
++  "Posix SHM mapping",
++  open_mapping_pshm,
++  close_mapping_file,
++  alloc_mapping_file,
++  free_mapping_file,
++  realloc_mapping_file,
++  munmap_mapping_file,
++  alias_mapping_file
++};
++#endif
++
++struct mappingdrivers mappingdriver_file = {
++  "mapfile",
++  "temp file mapping",
++  open_mapping_file,
++  close_mapping_file,
++  alloc_mapping_file,
++  free_mapping_file,
++  realloc_mapping_file,
++  munmap_mapping_file,
++  alias_mapping_file
++};
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.d b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.d
new file mode 100644
index 0000000000..c6bf6d7310
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.d
@@ -0,0 +1,18 @@
+$NetBSD$
+
+--- src/arch/netbsd/mapping/mapfile.d.orig	2017-11-02 06:34:44.093536595 +0000
++++ src/arch/netbsd/mapping/mapfile.d
+@@ -0,0 +1,13 @@
++mapfile.o: mapfile.c ../../../../src/include/config.h \
++  ../../../../src/include/emu.h ../../../../src/include/types.h \
++  ../../../../src/include/cpu.h ../../../../src/include/pic.h \
++  ../../../../src/include/bios.h ../../../../src/include/memory.h \
++  ../../../../src/include/vm86_compat.h ../../../../src/include/priv.h \
++  ../../../../src/include/mouse.h \
++  ../../../../src/include/keyboard/keyboard.h \
++  ../../../../src/include/dosemu_config.h \
++  ../../../../src/plugin/include/plugin_config.h \
++  ../../../../src/include/translate/unicode_symbols.h \
++  ../../../../src/include/dosemu_debug.h \
++  ../../../../src/include/mapping.h ../../../../src/include/smalloc.h \
++  ../../../../src/include/utilities.h
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.o b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.o
new file mode 100644
index 0000000000..89bc4500a2
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapfile.o
@@ -0,0 +1,3 @@
+$NetBSD$
+
+Binary files src/arch/netbsd/mapping/mapfile.o.orig and src/arch/netbsd/mapping/mapfile.o differ
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mapping_mapping.c b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapping.c
new file mode 100644
index 0000000000..9b0bbd1082
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapping.c
@@ -0,0 +1,786 @@
+$NetBSD$
+
+--- src/arch/netbsd/mapping/mapping.c.orig	2017-11-02 06:34:44.095265171 +0000
++++ src/arch/netbsd/mapping/mapping.c
+@@ -0,0 +1,781 @@
++/*
++ * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team".
++ *
++ * for details see file COPYING in the DOSEMU distribution
++ */
++
++/*
++ * Purpose: memory mapping library.
++ *
++ * Authors: Stas Sergeev, Bart Oldeman.
++ * Initially started by Hans Lermen, old copyrights below:
++ */
++/* file mapping.c
++ *
++ * generic mapping driver interface
++ * (C) Copyright 2000, Hans Lermen, lermen%fgan.de@localhost
++ *
++ * NOTE: We handle _all_ memory mappings within the mapping drivers,
++ *       mmap-type as well as IPC shm, except for X-mitshm (in X.c),
++ *       which is a special case and doesn't involve DOS space atall.
++ *
++ *       If you ever need to do mapping within DOSEMU (except X-mitshm),
++ *       _always_ use the interface supplied by the mapping drivers!
++ *       ^^^^^^^^         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++ */
++
++#include "emu.h"
++#include "hma.h"
++#include "utilities.h"
++#include "dos2linux.h"
++#include "kvm.h"
++#include "mapping.h"
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <sys/mman.h>
++#include <fcntl.h>
++
++#ifndef __x86_64__
++#undef MAP_32BIT
++#define MAP_32BIT 0
++#endif
++
++struct mem_map_struct {
++  off_t src;
++  void *base;
++  void *bkp_base;
++  dosaddr_t dst;
++  int len;
++  int mapped;
++};
++
++#define MAX_KMEM_MAPPINGS 4096
++static int kmem_mappings = 0;
++static struct mem_map_struct kmem_map[MAX_KMEM_MAPPINGS];
++
++static int init_done = 0;
++unsigned char *mem_base;
++char *lowmem_base;
++
++static struct mappingdrivers *mappingdrv[] = {
++#ifdef HAVE_SHM_OPEN
++  &mappingdriver_shm, /* first try shm_open */
++#endif
++  &mappingdriver_ashm,  /* then anon-shared-mmap */
++  &mappingdriver_file, /* and then a temp file */
++};
++
++static struct mappingdrivers *mappingdriver;
++
++/* The alias map is used to track alias mappings from the first 1MB + HMA
++   to the corresponding addresses in Linux address space (either lowmem,
++   vgaemu, or EMS). The DOS address (&mem_base[address]) may be r/w
++   protected by cpuemu or vgaemu, but the alias is never protected,
++   so it can be used to write without needing to unprotect and reprotect
++   afterwards.
++   If the alias is not used (hardware RAM from /dev/mem, or DPMI memory
++   (aliasing using fn 0x509 is safely ignored here)),
++   the address is identity-mapped to &mem_base[address].
++*/
++static unsigned char *aliasmap[(LOWMEM_SIZE+HMASIZE)/PAGE_SIZE];
++
++static void update_aliasmap(dosaddr_t dosaddr, size_t mapsize,
++			    unsigned char *unixaddr)
++{
++  unsigned int dospage, i;
++
++  if (dosaddr >= LOWMEM_SIZE+HMASIZE)
++    return;
++  dospage = dosaddr >> PAGE_SHIFT;
++  for (i = 0; i < mapsize >> PAGE_SHIFT; i++)
++    aliasmap[dospage + i] = unixaddr ? unixaddr + (i << PAGE_SHIFT) : NULL;
++}
++
++void *dosaddr_to_unixaddr(unsigned int addr)
++{
++  if (addr < LOWMEM_SIZE + HMASIZE && aliasmap[addr >> PAGE_SHIFT])
++    return aliasmap[addr >> PAGE_SHIFT] + (addr & (PAGE_SIZE - 1));
++  return MEM_BASE32(addr);
++}
++
++void *physaddr_to_unixaddr(unsigned int addr)
++{
++  if (addr < LOWMEM_SIZE + HMASIZE)
++    return dosaddr_to_unixaddr(addr);
++  /* XXX something other than XMS? */
++  return &ext_mem_base[addr - (LOWMEM_SIZE + HMASIZE)];
++}
++
++static int map_find_idx(struct mem_map_struct *map, int max, off_t addr)
++{
++  int i;
++  for (i = 0; i < max; i++) {
++    if (map[i].src == addr)
++      return i;
++  }
++  return -1;
++}
++
++static int map_find(struct mem_map_struct *map, int max,
++  dosaddr_t addr, int size, int mapped)
++{
++  int i;
++  dosaddr_t dst, dst1;
++  dosaddr_t min = -1;
++  int idx = -1;
++  dosaddr_t max_addr = addr + size;
++  for (i = 0; i < max; i++) {
++    if (!map[i].dst || !map[i].len || map[i].mapped != mapped)
++      continue;
++    dst = map[i].dst;
++    dst1 = dst + map[i].len;
++    if (dst >= addr && dst < max_addr) {
++      if (min == (dosaddr_t)-1 || dst < min) {
++        min = dst;
++        idx = i;
++      }
++    }
++    if (dst1 > addr && dst < max_addr) {
++      if (min == (dosaddr_t)-1 || dst1 < min) {
++        min = addr;
++        idx = i;
++      }
++    }
++  }
++  return idx;
++}
++
++static dosaddr_t kmem_unmap_single(int idx)
++{
++  kmem_map[idx].base = mmap(0, kmem_map[idx].len, PROT_NONE,
++	       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
++  mremap(MEM_BASE32(kmem_map[idx].dst), kmem_map[idx].len,
++      kmem_map[idx].len, MREMAP_MAYMOVE | MREMAP_FIXED, kmem_map[idx].base);
++  kmem_map[idx].mapped = 0;
++  update_aliasmap(kmem_map[idx].dst, kmem_map[idx].len, NULL);
++  return kmem_map[idx].dst;
++}
++
++static int kmem_unmap_mapping(dosaddr_t addr, int mapsize)
++{
++  int i, cnt = 0;
++
++  while ((i = map_find(kmem_map, kmem_mappings, addr, mapsize, 1)) != -1) {
++    kmem_unmap_single(i);
++    cnt++;
++  }
++  return cnt;
++}
++
++static void kmem_map_single(int idx, dosaddr_t targ)
++{
++  assert(targ != (dosaddr_t)-1);
++  mremap(kmem_map[idx].base, kmem_map[idx].len, kmem_map[idx].len,
++      MREMAP_MAYMOVE | MREMAP_FIXED, MEM_BASE32(targ));
++  kmem_map[idx].dst = targ;
++  kmem_map[idx].mapped = 1;
++  update_aliasmap(targ, kmem_map[idx].len, kmem_map[idx].bkp_base);
++}
++
++void *alias_mapping_high(int cap, size_t mapsize, int protect, void *source)
++{
++  void *target = (void *)-1;
++
++#ifdef __x86_64__
++  /* use MAP_32BIT also for MAPPING_INIT_LOWRAM until simx86 is 64bit-safe */
++  if (cap & (MAPPING_DPMI|MAPPING_VGAEMU|MAPPING_INIT_LOWRAM)) {
++    target = mmap(NULL, mapsize, protect,
++		MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
++    if (target == MAP_FAILED) {
++      error("mmap MAP_32BIT failed, %s\n", strerror(errno));
++      return MAP_FAILED;
++    }
++  }
++#endif
++
++  return mappingdriver->alias(cap, target, mapsize, protect, source);
++}
++
++int alias_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect, void *source)
++{
++  void *target, *addr;
++  int ku;
++
++  assert(targ != (dosaddr_t)-1);
++  Q__printf("MAPPING: alias, cap=%s, targ=%#x, size=%zx, protect=%x, source=%p\n",
++	cap, targ, mapsize, protect, source);
++  /* for non-zero INIT_LOWRAM the target is a hint */
++  target = MEM_BASE32(targ);
++  ku = kmem_unmap_mapping(targ, mapsize);
++  if (ku)
++    dosemu_error("Found %i kmem mappings at %#x\n", ku, targ);
++
++  addr = mappingdriver->alias(cap, target, mapsize, protect, source);
++  if (addr == MAP_FAILED)
++    return -1;
++  if (targ != (dosaddr_t)-1)
++    update_aliasmap(targ, mapsize, source);
++  if (config.cpu_vm == CPUVM_KVM)
++    mprotect_kvm(addr, mapsize, protect);
++  Q__printf("MAPPING: %s alias created at %p\n", cap, addr);
++
++  return 0;
++}
++
++static void *mmap_mapping_kmem(int cap, dosaddr_t targ, size_t mapsize,
++	off_t source)
++{
++  int i;
++  void *target;
++
++  Q__printf("MAPPING: map kmem, cap=%s, target=%x, size=%zx, source=%#jx\n",
++	cap, targ, mapsize, (intmax_t)source);
++
++  i = map_find_idx(kmem_map, kmem_mappings, source);
++  if (i == -1) {
++	error("KMEM mapping for %#jx was not allocated!\n", (intmax_t)source);
++	return MAP_FAILED;
++  }
++  if (kmem_map[i].len != mapsize) {
++	error("KMEM mapping for %#jx allocated for size %#x, but %#zx requested\n",
++	      (intmax_t)source, kmem_map[i].len, mapsize);
++	return MAP_FAILED;
++  }
++
++  if (targ == (dosaddr_t)-1) {
++    target = mmap(NULL, mapsize, PROT_READ | PROT_WRITE,
++                MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
++    if (target == MAP_FAILED) {
++      error("mmap MAP_32BIT failed, %s\n", strerror(errno));
++      return target;
++    }
++    targ = DOSADDR_REL(target);
++  } else {
++    target = MEM_BASE32(targ);
++  }
++  kmem_map_single(i, targ);
++
++  return target;
++}
++
++static void munmap_mapping_kmem(int cap, dosaddr_t addr, size_t mapsize)
++{
++  int i, rc;
++
++  Q__printf("MAPPING: unmap kmem, cap=%s, target=%x, size=%zx\n",
++	cap, addr, mapsize);
++
++  while ((i = map_find(kmem_map, kmem_mappings, addr, mapsize, 1)) != -1) {
++    dosaddr_t old_vbase = kmem_unmap_single(i);
++    if (!(cap & MAPPING_SCRATCH))
++      continue;
++    if (old_vbase < LOWMEM_SIZE) {
++      rc = alias_mapping(MAPPING_LOWMEM, old_vbase, mapsize,
++	    PROT_READ | PROT_WRITE, LOWMEM(old_vbase));
++    } else {
++      unsigned char *p;
++      p = mmap_mapping_ux(MAPPING_SCRATCH, MEM_BASE32(old_vbase), mapsize,
++          PROT_READ | PROT_WRITE);
++      if (p == MAP_FAILED)
++        rc = -1;
++    }
++    if (rc == -1) {
++      error("failure unmapping kmem region\n");
++      continue;
++    }
++  }
++}
++
++static int mapping_is_hole(void *start, size_t size)
++{
++  unsigned beg = (uintptr_t)start;
++  unsigned end = beg + size;
++  return (mapping_find_hole(beg, end, size) == start);
++}
++
++static void *do_mmap_mapping(int cap, void *target, size_t mapsize, int protect)
++{
++  void *addr;
++  int flags = (target != (void *)-1) ? MAP_FIXED : 0;
++
++  if (cap & MAPPING_NOOVERLAP) {
++    if (!flags)
++      cap &= ~MAPPING_NOOVERLAP;
++    else if (target)
++      flags &= ~MAP_FIXED;
++    /* not removing MAP_FIXED when mapping to 0 */
++    else if (!mapping_is_hole(target, mapsize))
++      return MAP_FAILED;
++  }
++  if (target == (void *)-1) target = NULL;
++#ifdef __x86_64__
++  if (flags == 0 && (cap & (MAPPING_DPMI|MAPPING_VGAEMU|MAPPING_INIT_LOWRAM)))
++    flags = MAP_32BIT;
++#endif
++  addr = mmap(target, mapsize, protect,
++		MAP_PRIVATE | flags | MAP_ANONYMOUS, -1, 0);
++  if (addr == MAP_FAILED)
++    return addr;
++  if ((cap & MAPPING_NOOVERLAP) && addr != target) {
++    munmap(addr, mapsize);
++    return MAP_FAILED;
++  }
++
++  return addr;
++}
++
++void *mmap_mapping_ux(int cap, void *target, size_t mapsize, int protect)
++{
++  return do_mmap_mapping(cap, target, mapsize, protect);
++}
++
++void *mmap_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect)
++{
++  void *addr;
++  void *target = ((targ == (dosaddr_t)-1) ? (void *)-1 : MEM_BASE32(targ));
++
++  Q__printf("MAPPING: map, cap=%s, target=%p, size=%zx, protect=%x\n",
++	cap, target, mapsize, protect);
++  if (!(cap & MAPPING_INIT_LOWRAM) && targ != (dosaddr_t)-1) {
++    int ku;
++    /* for lowram we use alias_mapping() instead */
++    assert(targ >= LOWMEM_SIZE);
++    ku = kmem_unmap_mapping(targ, mapsize);
++    if (ku)
++      dosemu_error("Found %i kmem mappings at %#x\n", ku, targ);
++  }
++
++  addr = do_mmap_mapping(cap, target, mapsize, protect);
++  if (addr == MAP_FAILED)
++    return MAP_FAILED;
++  if (targ != (dosaddr_t)-1)
++    update_aliasmap(targ, mapsize, addr);
++  Q__printf("MAPPING: map success, cap=%s, addr=%p\n", cap, addr);
++  if (config.cpu_vm == CPUVM_KVM)
++    mprotect_kvm(addr, mapsize, protect);
++  return addr;
++}
++
++int mprotect_mapping(int cap, dosaddr_t targ, size_t mapsize, int protect)
++{
++  int ret;
++  void *addr = MEM_BASE32(targ);
++
++  Q__printf("MAPPING: mprotect, cap=%s, addr=%p, size=%zx, protect=%x\n",
++	cap, addr, mapsize, protect);
++  /* it is important to r/o protect the KVM guest page tables BEFORE
++     calling mprotect as this function is called by parallel threads
++     (vgaemu.c:_vga_emu_update).
++     Otherwise the page can be r/w in the guest but r/o on the host which
++     causes KVM to exit with EFAULT when the guest writes there.
++     We do not need to worry about caching/TLBs because the kernel will
++     walk the guest page tables (see kernel:
++     Documentation/virtual/kvm/mmu.txt:
++     - if needed, walk the guest page tables to determine the guest translation
++       (gva->gpa or ngpa->gpa)
++       - if permissions are insufficient, reflect the fault back to the guest)
++  */
++  if (config.cpu_vm == CPUVM_KVM)
++    mprotect_kvm(addr, mapsize, protect);
++  ret = mprotect(addr, mapsize, protect);
++  if (ret)
++    error("mprotect() failed: %s\n", strerror(errno));
++  return ret;
++}
++
++/*
++ * This gets called on DOSEMU startup to determine the kind of mapping
++ * and setup the appropriate function pointers
++ */
++void mapping_init(void)
++{
++  int i, found = -1;
++  int numdrivers = sizeof(mappingdrv) / sizeof(mappingdrv[0]);
++
++  if (init_done) return;
++
++  if (config.mappingdriver && strcmp(config.mappingdriver, "auto")) {
++    /* first try the mapping driver the user wants */
++    for (i=0; i < numdrivers; i++) {
++      if (!strcmp(mappingdrv[i]->key, config.mappingdriver)) {
++        found = i;
++        break;
++      }
++    }
++    if (found < 0) {
++      error("Wrong mapping driver specified: %s\n", config.mappingdriver);
++      leavedos(2);
++    }
++  }
++  if (found < 0) found = 0;
++  for (i=found; i < numdrivers; i++) {
++    if (mappingdrv[i] && (*mappingdrv[i]->open)(MAPPING_PROBE)) {
++      mappingdriver = mappingdrv[i];
++      Q_printf("MAPPING: using the %s driver\n", mappingdriver->name);
++      init_done = 1;
++      return;
++    }
++    if (found > 0) {
++      found = -1;
++      /* As we want to restart the loop, because of 'i++' at end of loop,
++       * we need to set 'i = -1'
++       */
++      i = -1;
++    }
++  }
++  error("MAPPING: cannot allocate an appropriate mapping driver\n");
++  leavedos(2);
++}
++
++/* this gets called on DOSEMU termination cleanup all mapping stuff */
++void mapping_close(void)
++{
++  if (init_done && mappingdriver->close) close_mapping(MAPPING_ALL);
++}
++
++static char dbuf[256];
++char *decode_mapping_cap(int cap)
++{
++  char *p = dbuf;
++  p[0] = 0;
++  if (!cap) return dbuf;
++  if ((cap & MAPPING_ALL) == MAPPING_ALL) {
++    p += sprintf(p, " ALL");
++  }
++  else {
++    if (cap & MAPPING_OTHER) p += sprintf(p, " OTHER");
++    if (cap & MAPPING_EMS) p += sprintf(p, " EMS");
++    if (cap & MAPPING_DPMI) p += sprintf(p, " DPMI");
++    if (cap & MAPPING_VGAEMU) p += sprintf(p, " VGAEMU");
++    if (cap & MAPPING_VIDEO) p += sprintf(p, " VIDEO");
++    if (cap & MAPPING_VC) p += sprintf(p, " VC");
++    if (cap & MAPPING_HGC) p += sprintf(p, " HGC");
++    if (cap & MAPPING_HMA) p += sprintf(p, " HMA");
++    if (cap & MAPPING_SHARED) p += sprintf(p, " SHARED");
++    if (cap & MAPPING_INIT_HWRAM) p += sprintf(p, " INIT_HWRAM");
++    if (cap & MAPPING_INIT_LOWRAM) p += sprintf(p, " INIT_LOWRAM");
++    if (cap & MAPPING_EXTMEM) p += sprintf(p, " EXTMEM");
++  }
++  if (cap & MAPPING_KMEM) p += sprintf(p, " KMEM");
++  if (cap & MAPPING_LOWMEM) p += sprintf(p, " LOWMEM");
++  if (cap & MAPPING_SCRATCH) p += sprintf(p, " SCRATCH");
++  if (cap & MAPPING_SINGLE) p += sprintf(p, " SINGLE");
++  if (cap & MAPPING_MAYSHARE) p += sprintf(p, " MAYSHARE");
++  return dbuf;
++}
++
++int open_mapping(int cap)
++{
++  return mappingdriver->open(cap);
++}
++
++void close_mapping(int cap)
++{
++  if (mappingdriver->close) mappingdriver->close(cap);
++}
++
++static void *alloc_mapping_kmem(size_t mapsize, off_t source)
++{
++    void *addr, *addr2;
++
++    Q_printf("MAPPING: alloc kmem, source=%#jx size=%#zx\n",
++             (intmax_t)source, mapsize);
++    if (source == -1) {
++      error("KMEM mapping without source\n");
++      leavedos(64);
++    }
++    if (map_find_idx(kmem_map, kmem_mappings, source) != -1) {
++      error("KMEM mapping for %#jx allocated twice!\n", (intmax_t)source);
++      return MAP_FAILED;
++    }
++    open_kmem();
++    addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_32BIT,
++		mem_fd, source);
++    addr2 = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_32BIT,
++		mem_fd, source);
++    close_kmem();
++    if (addr == MAP_FAILED || addr2 == MAP_FAILED)
++      return MAP_FAILED;
++
++    kmem_map[kmem_mappings].src = source;
++    kmem_map[kmem_mappings].base = addr;
++    kmem_map[kmem_mappings].bkp_base = addr2;
++    kmem_map[kmem_mappings].dst = -1;
++    kmem_map[kmem_mappings].len = mapsize;
++    kmem_map[kmem_mappings].mapped = 0;
++    kmem_mappings++;
++    Q_printf("MAPPING: region allocated at %p\n", addr);
++    return addr;
++}
++
++void *alloc_mapping(int cap, size_t mapsize)
++{
++  void *addr;
++
++  Q__printf("MAPPING: alloc, cap=%s size=%#zx\n", cap, mapsize);
++  addr = mappingdriver->alloc(cap, mapsize);
++  mprotect(addr, mapsize, PROT_READ | PROT_WRITE);
++
++  if (cap & MAPPING_INIT_LOWRAM) {
++    Q__printf("MAPPING: LOWRAM_INIT, cap=%s, base=%p\n", cap, addr);
++    lowmem_base = addr;
++  }
++  Q__printf("MAPPING: %s allocated at %p\n", cap, addr);
++  return addr;
++}
++
++void free_mapping(int cap, void *addr, size_t mapsize)
++{
++  if (cap & MAPPING_KMEM) {
++    return;
++  }
++  mprotect(addr, mapsize, PROT_READ | PROT_WRITE);
++  mappingdriver->free(cap, addr, mapsize);
++}
++
++void *realloc_mapping(int cap, void *addr, size_t oldsize, size_t newsize)
++{
++  if (!addr) {
++    if (oldsize)  // no-no, realloc of the lowmem is not good too
++      dosemu_error("realloc_mapping() called with addr=NULL, oldsize=%#zx\n", oldsize);
++    Q_printf("MAPPING: realloc from NULL changed to malloc\n");
++    return alloc_mapping(cap, newsize);
++  }
++  if (!oldsize)
++    dosemu_error("realloc_mapping() addr=%p, oldsize=0\n", addr);
++  return mappingdriver->realloc(cap, addr, oldsize, newsize);
++}
++
++int munmap_mapping(int cap, dosaddr_t targ, size_t mapsize)
++{
++  int ku;
++  /* First of all remap the kmem mappings */
++  ku = kmem_unmap_mapping(targ, mapsize);
++  if (ku)
++    dosemu_error("Found %i kmem mappings at %#x\n", ku, targ);
++
++  if (cap & MAPPING_KMEM) {
++      /* Already done */
++      return 0;
++  }
++
++  return mappingdriver->munmap(cap, MEM_BASE32(targ), mapsize);
++}
++
++struct hardware_ram {
++  size_t base;
++  dosaddr_t default_vbase;
++  dosaddr_t vbase;
++  size_t size;
++  int type;
++  struct hardware_ram *next;
++};
++
++static struct hardware_ram *hardware_ram;
++
++static int do_map_hwram(struct hardware_ram *hw)
++{
++  unsigned char *p;
++
++  p = mmap_mapping_kmem(MAPPING_KMEM, hw->default_vbase, hw->size, hw->base);
++  if (p == MAP_FAILED) {
++    error("mmap error in map_hardware_ram %s\n", strerror (errno));
++    return -1;
++  }
++  hw->vbase = DOSADDR_REL(p);
++  g_printf("mapped hardware ram at 0x%08zx .. 0x%08zx at %#x\n",
++	     hw->base, hw->base+hw->size-1, hw->vbase);
++  return 0;
++}
++
++/*
++ * DANG_BEGIN_FUNCTION init_hardware_ram
++ *
++ * description:
++ *  Initialize the hardware direct-mapped pages
++ *
++ * DANG_END_FUNCTION
++ */
++void init_hardware_ram(void)
++{
++  struct hardware_ram *hw;
++
++  for (hw = hardware_ram; hw != NULL; hw = hw->next) {
++    if (hw->type == 'e')  /* virtual hardware ram mapped later */
++      continue;
++    alloc_mapping_kmem(hw->size, hw->base);
++    if (do_map_hwram(hw) == -1)
++      return;
++  }
++}
++
++int map_hardware_ram(char type)
++{
++  struct hardware_ram *hw;
++
++  for (hw = hardware_ram; hw != NULL; hw = hw->next) {
++    if (hw->type != type || hw->vbase != -1)
++      continue;
++    if (do_map_hwram(hw) == -1)
++      return -1;
++  }
++  return 0;
++}
++
++int map_hardware_ram_manual(size_t base, dosaddr_t vbase)
++{
++  struct hardware_ram *hw;
++
++  for (hw = hardware_ram; hw != NULL; hw = hw->next) {
++    if (hw->base != base)
++      continue;
++    hw->vbase = vbase;
++    return 0;
++  }
++  return -1;
++}
++
++int unmap_hardware_ram(char type)
++{
++  struct hardware_ram *hw;
++  int rc = 0;
++
++  for (hw = hardware_ram; hw != NULL; hw = hw->next) {
++    if (hw->type != type || hw->vbase == -1)
++      continue;
++    munmap_mapping_kmem(MAPPING_KMEM, hw->vbase, hw->size);
++    g_printf("unmapped hardware ram at 0x%08zx .. 0x%08zx at %#x\n",
++	    hw->base, hw->base+hw->size-1, hw->vbase);
++    hw->vbase = -1;
++  }
++  return rc;
++}
++
++int register_hardware_ram(int type, unsigned int base, unsigned int size)
++{
++  struct hardware_ram *hw;
++
++  if (!can_do_root_stuff && type != 'e') {
++    dosemu_error("can't use hardware ram in low feature (non-suid root) DOSEMU\n");
++    return 0;
++  }
++  c_printf("Registering HWRAM, type=%c base=%#x size=%#x\n", type, base, size);
++  hw = malloc(sizeof(*hw));
++  hw->base = base;
++  if (base < LOWMEM_SIZE)
++    hw->default_vbase = hw->base;
++  else
++    hw->default_vbase = -1;
++  hw->vbase = -1;
++  hw->size = size;
++  hw->type = type;
++  hw->next = hardware_ram;
++  hardware_ram = hw;
++  if (base >= LOWMEM_SIZE || type == 'h')
++    memcheck_reserve(type, base, size);
++  return 1;
++}
++
++/* given physical address addr, gives the corresponding vbase or -1 */
++unsigned get_hardware_ram(unsigned addr)
++{
++  struct hardware_ram *hw;
++
++  for (hw = hardware_ram; hw != NULL; hw = hw->next)
++    if (hw->vbase != -1 &&
++	hw->base <= addr && addr < hw->base + hw->size)
++      return hw->vbase + addr - hw->base;
++  return -1;
++}
++
++void list_hardware_ram(void (*print)(const char *, ...))
++{
++  struct hardware_ram *hw;
++
++  (*print)("hardware_ram: %s\n", hardware_ram ? "" : "no");
++  if (!hardware_ram) return;
++  (*print)("hardware_pages:\n");
++  for (hw = hardware_ram; hw != NULL; hw = hw->next)
++    (*print)("%08x-%08x\n", hw->base, hw->base + hw->size - 1);
++}
++
++/* why count ??? */
++/* Because you do not want to open it more than once! */
++static u_char kmem_open_count = 0;
++
++void
++open_kmem (void)
++{
++  PRIV_SAVE_AREA
++  /* as I understad it, /dev/kmem is the kernel's view of memory,
++     * and /dev/mem is the identity-mapped (i.e. physical addressed)
++     * memory. Currently under Linux, both are the same.
++     */
++
++  kmem_open_count++;
++
++  if (mem_fd != -1)
++    return;
++  enter_priv_on();
++  mem_fd = open("/dev/mem", O_RDWR);
++  leave_priv_setting();
++  if (mem_fd < 0)
++    {
++      error("can't open /dev/mem: errno=%d, %s \n",
++	     errno, strerror (errno));
++      leavedos (0);
++      return;
++    }
++  g_printf ("Kmem opened successfully\n");
++}
++
++void
++close_kmem (void)
++{
++
++  if (kmem_open_count)
++    {
++      kmem_open_count--;
++      if (kmem_open_count)
++	return;
++      close (mem_fd);
++      mem_fd = -1;
++      v_printf ("Kmem closed successfully\n");
++    }
++}
++
++void *mapping_find_hole(unsigned long start, unsigned long stop,
++	unsigned long size)
++{
++    FILE *fp;
++    unsigned long beg, end, pend;
++    int fd, ret;
++    /* find out whether the address request is available */
++    fd = dup(dosemu_proc_self_maps_fd);
++    if ((fp = fdopen(fd, "r")) == NULL) {
++	error("can't open /proc/self/maps\n");
++	return MAP_FAILED;
++    }
++    fseek(fp, 0, SEEK_SET);
++    pend = start;
++    while ((ret = fscanf(fp, "%lx-%lx%*[^\n]", &beg, &end)) == 2) {
++	if (beg <= start) {
++	    if (end > pend)
++		pend = end;
++	    continue;
++	}
++	if (beg - pend >= size)
++	    break;
++	if (end + size > stop) {
++	    fclose(fp);
++	    return MAP_FAILED;
++	}
++	pend = end;
++    }
++    fclose(fp);
++    if (ret != 2)
++	return MAP_FAILED;
++    return (void *)pend;
++}
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mapping_mapping.d b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapping.d
new file mode 100644
index 0000000000..4e00a9b0ea
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapping.d
@@ -0,0 +1,19 @@
+$NetBSD$
+
+--- src/arch/netbsd/mapping/mapping.d.orig	2017-11-02 06:34:44.096118355 +0000
++++ src/arch/netbsd/mapping/mapping.d
+@@ -0,0 +1,14 @@
++mapping.o: mapping.c ../../../../src/include/config.h \
++  ../../../../src/include/emu.h ../../../../src/include/types.h \
++  ../../../../src/include/cpu.h ../../../../src/include/pic.h \
++  ../../../../src/include/bios.h ../../../../src/include/memory.h \
++  ../../../../src/include/vm86_compat.h ../../../../src/include/priv.h \
++  ../../../../src/include/mouse.h \
++  ../../../../src/include/keyboard/keyboard.h \
++  ../../../../src/include/dosemu_config.h \
++  ../../../../src/plugin/include/plugin_config.h \
++  ../../../../src/include/translate/unicode_symbols.h \
++  ../../../../src/include/dosemu_debug.h ../../../../src/include/hma.h \
++  ../../../../src/include/utilities.h \
++  ../../../../src/include/dos2linux.h ../../../../src/include/kvm.h \
++  ../../../../src/include/mapping.h
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mapping_mapshm.c b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapshm.c
new file mode 100644
index 0000000000..fc50df4a69
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapshm.c
@@ -0,0 +1,195 @@
+$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,
++};
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mapping_mapshm.d b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapshm.d
new file mode 100644
index 0000000000..cd0df75180
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mapping_mapshm.d
@@ -0,0 +1,17 @@
+$NetBSD$
+
+--- src/arch/netbsd/mapping/mapshm.d.orig	2017-11-02 06:34:44.097829234 +0000
++++ src/arch/netbsd/mapping/mapshm.d
+@@ -0,0 +1,12 @@
++mapshm.o: mapshm.c ../../../../src/include/config.h \
++  ../../../../src/include/emu.h ../../../../src/include/types.h \
++  ../../../../src/include/cpu.h ../../../../src/include/pic.h \
++  ../../../../src/include/bios.h ../../../../src/include/memory.h \
++  ../../../../src/include/vm86_compat.h ../../../../src/include/priv.h \
++  ../../../../src/include/mouse.h \
++  ../../../../src/include/keyboard/keyboard.h \
++  ../../../../src/include/dosemu_config.h \
++  ../../../../src/plugin/include/plugin_config.h \
++  ../../../../src/include/translate/unicode_symbols.h \
++  ../../../../src/include/dosemu_debug.h \
++  ../../../../src/include/mapping.h
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_386-ucontext.h b/dosemu2/patches/patch-src_arch_netbsd_mcontext_386-ucontext.h
new file mode 100644
index 0000000000..2233979bd6
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_386-ucontext.h
@@ -0,0 +1,65 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/386-ucontext.h.orig	2017-11-02 06:34:51.947631491 +0000
++++ src/arch/netbsd/mcontext/386-ucontext.h
+@@ -0,0 +1,60 @@
++/*-
++ * Copyright (c) 1999 Marcel Moolenaar
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer
++ *    in this position and unchanged.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * $FreeBSD: src/sys/i386/include/ucontext.h,v 1.4 1999/10/11 20:33:09 luoqi Exp $
++ */
++
++struct m_mcontext {
++	/*
++	 * The first 20 fields must match the definition of
++	 * sigcontext. So that we can support sigcontext
++	 * and ucontext_t at the same time.
++	 */
++	int	mc_onstack;		/* XXX - sigcontext compat. */
++	int	mc_gs;
++	int	mc_fs;
++	int	mc_es;
++	int	mc_ds;
++	int	mc_edi;
++	int	mc_esi;
++	int	mc_ebp;
++	int	mc_isp;
++	int	mc_ebx;
++	int	mc_edx;
++	int	mc_ecx;
++	int	mc_eax;
++	int	mc_trapno;
++	int	mc_err;
++	int	mc_eip;
++	int	mc_cs;
++	int	mc_eflags;
++	int	mc_esp;			/* machine state */
++	int	mc_ss;
++
++	int	mc_fpregs[28];		/* env87 + fpacc87 + u_long */
++	int	__spare__[17];
++};
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_COPYRIGHT b/dosemu2/patches/patch-src_arch_netbsd_mcontext_COPYRIGHT
new file mode 100644
index 0000000000..643323e55d
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_COPYRIGHT
@@ -0,0 +1,48 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/COPYRIGHT.orig	2017-11-02 06:34:51.948503101 +0000
++++ src/arch/netbsd/mcontext/COPYRIGHT
+@@ -0,0 +1,43 @@
++
++This software was developed as part of a project at MIT.
++
++Copyright (c) 2005-2007 Russ Cox,
++                   Massachusetts Institute of Technology
++
++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.
++
++===
++
++Contains parts of an earlier library that has:
++
++/*
++ * The authors of this software are Rob Pike, Sape Mullender, and Russ Cox
++ *		Copyright (c) 2003 by Lucent Technologies.
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose without fee is hereby granted, provided that this entire notice
++ * is included in all copies of any software which is or includes a copy
++ * or modification of this software and in all copies of the supporting
++ * documentation for such software.
++ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
++ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
++ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
++ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
++*/
++
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_Makefile b/dosemu2/patches/patch-src_arch_netbsd_mcontext_Makefile
new file mode 100644
index 0000000000..8e7fbd3a47
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_Makefile
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/Makefile.orig	2017-11-02 06:34:51.949371629 +0000
++++ src/arch/netbsd/mcontext/Makefile
+@@ -0,0 +1,9 @@
++top_builddir=../../../..
++include $(top_builddir)/Makefile.conf
++
++CFILES = context.c
++SFILES = asm.S
++
++all:  lib
++
++include $(REALTOPDIR)/src/Makefile.common
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_amd64-ucontext.h b/dosemu2/patches/patch-src_arch_netbsd_mcontext_amd64-ucontext.h
new file mode 100644
index 0000000000..4957aabd3e
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_amd64-ucontext.h
@@ -0,0 +1,81 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/amd64-ucontext.h.orig	2017-11-02 06:34:51.950237084 +0000
++++ src/arch/netbsd/mcontext/amd64-ucontext.h
+@@ -0,0 +1,76 @@
++/*-
++ * Copyright (c) 1999 Marcel Moolenaar
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer
++ *    in this position and unchanged.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * $FreeBSD: src/sys/i386/include/ucontext.h,v 1.4 1999/10/11 20:33:09 luoqi Exp $
++ */
++
++struct m_mcontext {
++	/*
++	 * The first 20 fields must match the definition of
++	 * sigcontext. So that we can support sigcontext
++	 * and ucontext_t at the same time.
++	 */
++	long	mc_onstack;		/* XXX - sigcontext compat. */
++	long	mc_rdi;			/* machine state (struct trapframe) */
++	long	mc_rsi;
++	long	mc_rdx;
++	long	mc_rcx;
++	long	mc_r8;
++	long	mc_r9;
++	long	mc_rax;
++	long	mc_rbx;
++	long	mc_rbp;
++	long	mc_r10;
++	long	mc_r11;
++	long	mc_r12;
++	long	mc_r13;
++	long	mc_r14;
++	long	mc_r15;
++	long	mc_trapno;
++	long	mc_addr;
++	long	mc_flags;
++	long	mc_err;
++	long	mc_rip;
++	long	mc_cs;
++	long	mc_rflags;
++	long	mc_rsp;
++	long	mc_ss;
++
++	long	mc_len;			/* sizeof(mcontext_t) */
++#define	_MC_FPFMT_NODEV		0x10000	/* device not present or configured */
++#define	_MC_FPFMT_XMM		0x10002
++	long	mc_fpformat;
++#define	_MC_FPOWNED_NONE	0x20000	/* FP state not used */
++#define	_MC_FPOWNED_FPU		0x20001	/* FP state came from FPU */
++#define	_MC_FPOWNED_PCB		0x20002	/* FP state came from PCB */
++	long	mc_ownedfp;
++	/*
++	 * See <machine/fpu.h> for the internals of mc_fpstate[].
++	 */
++	long	mc_fpstate[64];
++	long	mc_spare[8];
++};
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.S b/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.S
new file mode 100644
index 0000000000..7e18e2021c
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.S
@@ -0,0 +1,107 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/asm.S.orig	2017-11-02 06:34:51.951095202 +0000
++++ src/arch/netbsd/mcontext/asm.S
+@@ -0,0 +1,102 @@
++/* This code is taken from libtask library.
++ * Rip-off done by stsp for dosemu2 project.
++ * Original copyrights below. */
++
++/* Copyright (c) 2005-2006 Russ Cox, MIT; see COPYRIGHT */
++
++#if defined(__i386__)
++.globl _setmcontext
++_setmcontext:
++	movl	4(%esp), %eax
++
++	mov	8(%eax), %fs
++	mov	12(%eax), %es
++	mov	16(%eax), %ds
++	mov	76(%eax), %ss
++	movl	20(%eax), %edi
++	movl	24(%eax), %esi
++	movl	28(%eax), %ebp
++	movl	36(%eax), %ebx
++	movl	40(%eax), %edx
++	movl	44(%eax), %ecx
++
++	movl	72(%eax), %esp
++	pushl	60(%eax)	/* new %eip */
++	movl	48(%eax), %eax
++	ret
++
++.globl _getmcontext
++_getmcontext:
++	movl	4(%esp), %eax
++
++	mov	%fs, 8(%eax)
++	mov	%es, 12(%eax)
++	mov	%ds, 16(%eax)
++	mov	%ss, 76(%eax)
++	movl	%edi, 20(%eax)
++	movl	%esi, 24(%eax)
++	movl	%ebp, 28(%eax)
++	movl	%ebx, 36(%eax)
++	movl	%edx, 40(%eax)
++	movl	%ecx, 44(%eax)
++
++	movl	$1, 48(%eax)	/* %eax */
++	movl	(%esp), %ecx	/* %eip */
++	movl	%ecx, 60(%eax)
++	leal	4(%esp), %ecx	/* %esp */
++	movl	%ecx, 72(%eax)
++
++	movl	44(%eax), %ecx	/* restore %ecx */
++	movl	$0, %eax
++	ret
++#endif
++
++#if defined(__x86_64__)
++.globl _setmcontext
++_setmcontext:
++	movq	16(%rdi), %rsi
++	movq	24(%rdi), %rdx
++	movq	32(%rdi), %rcx
++	movq	40(%rdi), %r8
++	movq	48(%rdi), %r9
++	movq	56(%rdi), %rax
++	movq	64(%rdi), %rbx
++	movq	72(%rdi), %rbp
++	movq	80(%rdi), %r10
++	movq	88(%rdi), %r11
++	movq	96(%rdi), %r12
++	movq	104(%rdi), %r13
++	movq	112(%rdi), %r14
++	movq	120(%rdi), %r15
++	movq	184(%rdi), %rsp
++	pushq	160(%rdi)	/* new %eip */
++	movq	8(%rdi), %rdi
++	ret
++
++.globl _getmcontext
++_getmcontext:
++	movq	%rdi, 8(%rdi)
++	movq	%rsi, 16(%rdi)
++	movq	%rdx, 24(%rdi)
++	movq	%rcx, 32(%rdi)
++	movq	%r8, 40(%rdi)
++	movq	%r9, 48(%rdi)
++	movq	$1, 56(%rdi)	/* %rax */
++	movq	%rbx, 64(%rdi)
++	movq	%rbp, 72(%rdi)
++	movq	%r10, 80(%rdi)
++	movq	%r11, 88(%rdi)
++	movq	%r12, 96(%rdi)
++	movq	%r13, 104(%rdi)
++	movq	%r14, 112(%rdi)
++	movq	%r15, 120(%rdi)
++
++	movq	(%rsp), %rcx	/* %rip */
++	movq	%rcx, 160(%rdi)
++	leaq	8(%rsp), %rcx	/* %rsp */
++	movq	%rcx, 184(%rdi)
++
++	movq	32(%rdi), %rcx	/* restore %rcx */
++	movq	$0, %rax
++	ret
++#endif
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.d b/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.d
new file mode 100644
index 0000000000..7b6e702f74
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.d
@@ -0,0 +1,6 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/asm.d.orig	2017-11-02 06:34:51.951954137 +0000
++++ src/arch/netbsd/mcontext/asm.d
+@@ -0,0 +1 @@
++asm.o: asm.S
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.o b/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.o
new file mode 100644
index 0000000000..5b07e539e4
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_asm.o
@@ -0,0 +1,3 @@
+$NetBSD$
+
+Binary files src/arch/netbsd/mcontext/asm.o.orig and src/arch/netbsd/mcontext/asm.o differ
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.c b/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.c
new file mode 100644
index 0000000000..7375d6c81f
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.c
@@ -0,0 +1,68 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/context.c.orig	2017-11-02 06:34:51.953668414 +0000
++++ src/arch/netbsd/mcontext/context.c
+@@ -0,0 +1,63 @@
++/* This code is taken from libtask library.
++ * Rip-off done by stsp for dosemu2 project.
++ * Original copyrights below. */
++
++/* Copyright (c) 2005-2006 Russ Cox, MIT; see COPYRIGHT */
++
++#include <ucontext.h>
++#include <stdarg.h>
++#include <string.h>
++#include <inttypes.h>
++#include <assert.h>
++#include "mcontext.h"
++
++#if defined(__i386__)
++void
++makemcontext(m_ucontext_t *ucp, void (*func)(void), int argc, ...)
++{
++	int *sp;
++
++	sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4;
++	sp -= argc;
++	sp = (void*)((uintptr_t)sp - (uintptr_t)sp%16);	/* 16-align for OS X */
++	memmove(sp, &argc+1, argc*sizeof(int));
++
++	*--sp = 0;		/* return address */
++	ucp->uc_mcontext.mc_eip = (long)func;
++	ucp->uc_mcontext.mc_esp = (int)sp;
++}
++#endif
++
++#if defined(__x86_64__)
++void
++makemcontext(m_ucontext_t *ucp, void (*func)(void), int argc, ...)
++{
++	long *sp;
++	va_list va;
++
++	memset(&ucp->uc_mcontext, 0, sizeof ucp->uc_mcontext);
++	if (argc) {
++		assert(argc <= 2);	// oops
++		va_start(va, argc);
++		if (argc >= 1)
++			ucp->uc_mcontext.mc_rdi = va_arg(va, long);
++		if (argc >= 2)
++			ucp->uc_mcontext.mc_rsi = va_arg(va, long);
++		va_end(va);
++	}
++	sp = (long*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/sizeof(long);
++	sp -= argc;
++	sp = (void*)((uintptr_t)sp - (uintptr_t)sp%16);	/* 16-align for OS X */
++	*--sp = 0;	/* return address */
++	ucp->uc_mcontext.mc_rip = (long)func;
++	ucp->uc_mcontext.mc_rsp = (long)sp;
++}
++#endif
++
++int
++swapmcontext(m_ucontext_t *oucp, const m_ucontext_t *ucp)
++{
++	if(getmcontext(oucp) == 0)
++		setmcontext(ucp);
++	return 0;
++}
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.d b/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.d
new file mode 100644
index 0000000000..88c4dd10b5
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.d
@@ -0,0 +1,7 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/context.d.orig	2017-11-02 06:34:51.954526149 +0000
++++ src/arch/netbsd/mcontext/context.d
+@@ -0,0 +1,2 @@
++context.o: context.c ../../../../src/include/config.h mcontext.h \
++  amd64-ucontext.h
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.o b/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.o
new file mode 100644
index 0000000000..1d4160082a
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_context.o
@@ -0,0 +1,3 @@
+$NetBSD$
+
+Binary files src/arch/netbsd/mcontext/context.o.orig and src/arch/netbsd/mcontext/context.o differ
diff --git a/dosemu2/patches/patch-src_arch_netbsd_mcontext_mcontext.h b/dosemu2/patches/patch-src_arch_netbsd_mcontext_mcontext.h
new file mode 100644
index 0000000000..6fc102941f
--- /dev/null
+++ b/dosemu2/patches/patch-src_arch_netbsd_mcontext_mcontext.h
@@ -0,0 +1,58 @@
+$NetBSD$
+
+--- src/arch/netbsd/mcontext/mcontext.h.orig	2017-11-02 06:34:51.956237090 +0000
++++ src/arch/netbsd/mcontext/mcontext.h
+@@ -0,0 +1,53 @@
++/* This code is taken from libtask library.
++ * Rip-off done by stsp for dosemu2 project.
++ * Original copyrights below. */
++
++/* Copyright (c) 2005-2006 Russ Cox, MIT; see COPYRIGHT */
++
++#ifndef MCONTEXT_H
++#define MCONTEXT_H
++
++#include <ucontext.h>
++
++typedef struct m_mcontext m_mcontext_t;
++typedef struct m_ucontext m_ucontext_t;
++
++#	if defined(__i386__)
++#		include "386-ucontext.h"
++#	elif defined(__x86_64__)
++#		include "amd64-ucontext.h"
++#	else
++#		error Unsupported arch
++#	endif
++
++struct m_ucontext {
++	/*
++	 * Keep the order of the first two fields. Also,
++	 * keep them the first two fields in the structure.
++	 * This way we can have a union with struct
++	 * sigcontext and ucontext_t. This allows us to
++	 * support them both at the same time.
++	 * note: the union is not defined, though.
++	 */
++	sigset_t	uc_sigmask;
++	m_mcontext_t	uc_mcontext;
++
++	struct __ucontext *uc_link;
++	stack_t		uc_stack;
++	int		__spare__[8];
++};
++
++extern	int		_getmcontext(m_mcontext_t*);
++extern	int		_setmcontext(const m_mcontext_t*);
++static inline int setmcontext(const struct m_ucontext *u)
++{
++	return _setmcontext(&u->uc_mcontext);
++}
++static inline int getmcontext(struct m_ucontext *u)
++{
++	return _getmcontext(&u->uc_mcontext);
++}
++extern	int		swapmcontext(m_ucontext_t*, const m_ucontext_t*);
++extern	void		makemcontext(m_ucontext_t*, void(*)(void), int, ...);
++
++#endif
diff --git a/dosemu2/patches/patch-src_base_dev_misc_timers.c b/dosemu2/patches/patch-src_base_dev_misc_timers.c
new file mode 100644
index 0000000000..75d6ea44a5
--- /dev/null
+++ b/dosemu2/patches/patch-src_base_dev_misc_timers.c
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- src/base/dev/misc/timers.c.orig	2017-11-02 06:22:58.000000000 +0000
++++ src/base/dev/misc/timers.c
+@@ -29,7 +29,9 @@
+  */
+ 
+ #include <sys/time.h>
++#ifdef __linux__
+ #include <sys/kd.h>
++#endif
+ #include <sys/ioctl.h>
+ #include "config.h"
+ #include "emu.h"
diff --git a/dosemu2/patches/patch-src_base_kbd__unicode_getfd.c b/dosemu2/patches/patch-src_base_kbd__unicode_getfd.c
new file mode 100644
index 0000000000..8841075f24
--- /dev/null
+++ b/dosemu2/patches/patch-src_base_kbd__unicode_getfd.c
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- src/base/kbd_unicode/getfd.c.orig	2017-11-02 06:22:58.000000000 +0000
++++ src/base/kbd_unicode/getfd.c
+@@ -11,7 +11,9 @@
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <errno.h>
++#ifdef __linux__
+ #include <sys/kd.h>
++#endif
+ #include <sys/ioctl.h>
+ #include "priv.h"
+ #include "getfd.h"
diff --git a/dosemu2/patches/patch-src_base_kbd__unicode_keyb__raw.c b/dosemu2/patches/patch-src_base_kbd__unicode_keyb__raw.c
new file mode 100644
index 0000000000..ffbc57257d
--- /dev/null
+++ b/dosemu2/patches/patch-src_base_kbd__unicode_keyb__raw.c
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- src/base/kbd_unicode/keyb_raw.c.orig	2017-11-02 06:22:58.000000000 +0000
++++ src/base/kbd_unicode/keyb_raw.c
+@@ -9,7 +9,9 @@
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/stat.h>
++#ifdef __linux__
+ #include <sys/kd.h>
++#endif
+ #include <sys/ioctl.h>
+ 
+ #include "emu.h"
diff --git a/dosemu2/patches/patch-src_base_kbd__unicode_keymaps.c b/dosemu2/patches/patch-src_base_kbd__unicode_keymaps.c
new file mode 100644
index 0000000000..c5e5bc6db3
--- /dev/null
+++ b/dosemu2/patches/patch-src_base_kbd__unicode_keymaps.c
@@ -0,0 +1,15 @@
+$NetBSD$
+
+--- src/base/kbd_unicode/keymaps.c.orig	2017-11-02 06:22:58.000000000 +0000
++++ src/base/kbd_unicode/keymaps.c
+@@ -10,8 +10,10 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#ifdef __linux
+ #include <sys/kd.h>
+ #include <linux/keyboard.h>
++#endif
+ #include <sys/ioctl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
diff --git a/dosemu2/patches/patch-src_base_misc_libpcl_Makefile b/dosemu2/patches/patch-src_base_misc_libpcl_Makefile
new file mode 100644
index 0000000000..3af677b239
--- /dev/null
+++ b/dosemu2/patches/patch-src_base_misc_libpcl_Makefile
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- src/base/misc/libpcl/Makefile.orig	2017-11-02 06:22:58.000000000 +0000
++++ src/base/misc/libpcl/Makefile
+@@ -6,7 +6,8 @@
+ 
+ top_builddir=../../../..
+ include $(top_builddir)/Makefile.conf
+-ALL_CPPFLAGS += -I$(REALTOPDIR)/src/arch/linux/mcontext
++#ALL_CPPFLAGS += -I$(REALTOPDIR)/src/arch/linux/mcontext
++ALL_CPPFLAGS += -I$(REALTOPDIR)/src/arch/netbsd/mcontext
+ 
+ CFILES=pcl.c pcl_ctx.c
+ 
diff --git a/dosemu2/patches/patch-src_include_debug.h b/dosemu2/patches/patch-src_include_debug.h
new file mode 100644
index 0000000000..e357b04071
--- /dev/null
+++ b/dosemu2/patches/patch-src_include_debug.h
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- src/include/debug.h.orig	2017-11-02 06:22:58.000000000 +0000
++++ src/include/debug.h
+@@ -3,4 +3,8 @@
+  *
+  * for details see file COPYING in the DOSEMU distribution
+  */
++#ifdef __linux__
+ #include "../arch/linux/async/debug.h"
++#elif defined(__NetBSD__)
++#include "../arch/netbsd/async/debug.h"
++#endif


Home | Main Index | Thread Index | Old Index