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