From b39b25d07318b482e53350cbbb755b54fbd14973 Mon Sep 17 00:00:00 2001
From: pmai <pmai>
Date: Mon, 28 Jan 2002 20:19:39 +0000
Subject: [PATCH] Added specialised port to NetBSD (1.5.2) on x86.  Since the
 code-base was already cleaned up with the OpenBSD port, this doesn't require
 massive changes.

Since current NetBSD is ELF-based by default, we don't make use of the
ELF feature, or in other words:  The presence of the NetBSD feature
implies ELF, since there is no support for non-ELF NetBSD.

The page-protection feature of the generational GC had to be turned
off, because currently NetBSD 1.5.2 doesn't provide access to the
faulting memory address in SIGSEGV signal-handlers on the x86
platform.

The memory is validated/mmapped in 64MB chunks in os-validate, in
order to circumvent a restriction on NetBSD, that prevented me from
mmapping 128MB or more apiece.  It has been pointed out to me that
this may be caused by the default ulimit on data segment sizes, which
seems kind of strange, but might be true.  In any case the current
approach works OK, and doesn't require root interaction, so is
probably the better approach.
---
 lisp/NetBSD-os.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++
 lisp/gencgc.c    |  13 ++-
 2 files changed, 248 insertions(+), 3 deletions(-)
 create mode 100644 lisp/NetBSD-os.c

diff --git a/lisp/NetBSD-os.c b/lisp/NetBSD-os.c
new file mode 100644
index 000000000..57722a6b2
--- /dev/null
+++ b/lisp/NetBSD-os.c
@@ -0,0 +1,238 @@
+/*
+ * NetBSD-os.c.
+ * From OpenBSD-os.c 1.1 2001/12/06 19:15:44 pmai Exp
+ * From FreeBSD-os.c 1.6 2000/10/24 13:32:30 dtc Exp
+ *
+ * OS-dependent routines.  This file (along with os.h) exports an
+ * OS-independent interface to the operating system VM facilities.
+ * Suprisingly, this interface looks a lot like the Mach interface
+ * (but simpler in some places).  For some operating systems, a subset
+ * of these functions will have to be emulated.
+ *
+ * This is the OSF1 version.  By Sean Hallgren.
+ * Much hacked by Paul Werkowski
+ * GENCGC support by Douglas Crosher, 1996, 1997.
+ * Frobbed for OpenBSD by Pierre R. Mai, 2001.
+ * Frobbed for NetBSD by Pierre R. Mai, 2002.
+ *
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.c,v 1.1 2002/01/28 20:19:39 pmai Exp $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <errno.h>
+#include "./signal.h"
+#include "os.h"
+#include "arch.h"
+#include "globals.h"
+#include "interrupt.h"
+#include "lispregs.h"
+#include "internals.h"
+
+#include <sys/types.h>
+#include <signal.h>
+/* #include <sys/sysinfo.h> */
+#include <sys/proc.h>
+#include "validate.h"
+size_t os_vm_page_size;
+
+#define DPRINTF(t,a) {if (t) fprintf a;}
+
+#if defined GENCGC
+#include "gencgc.h"
+#endif
+
+
+void os_init(void)
+{
+  os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
+}
+
+int sc_reg(struct sigcontext *c, int offset)
+{
+  switch(offset)
+    {
+    case  0: return c->sc_eax;
+    case  2: return c->sc_ecx;
+    case  4: return c->sc_edx;
+    case  6: return c->sc_ebx;
+    case  8: return c->sc_esp;
+    case 10: return c->sc_ebp;
+    case 12: return c->sc_esi;
+    case 14: return c->sc_edi;
+    }
+  return 0;
+}
+
+void os_save_context(void)
+{
+  /*
+   * Called from interrupt handlers so C stuff knows things set in Lisp.
+   */
+}
+
+void os_set_context(void)
+{
+}
+
+os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)
+{
+  int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+
+  /*
+   * NetBSD 1.5.2 seems to insist on each mmap being less than 128MB.
+   * So we mmap in 64MB steps.  This is probably inefficient, but the
+   * missing CR2 reporting in signal handlers already ensures that
+   * NetBSD/x86 is not a suitable platform for CMU CL as it stands.
+   */
+  
+  if (addr)
+    flags |= MAP_FIXED;
+  else
+    flags |= MAP_VARIABLE;
+
+  DPRINTF(0, (stderr, "os_validate %x %d =>", addr, len));
+
+  if (addr)
+    {
+      os_vm_address_t curaddr=addr;
+
+      while (len>0)
+	{
+	  os_vm_address_t resaddr;
+	  int curlen=MIN(64*1024*1024,len);
+	  
+	  resaddr = mmap(curaddr, curlen, OS_VM_PROT_ALL, flags, -1, 0);
+	  
+	  if (resaddr == (os_vm_address_t) -1)
+	    {
+	      perror("mmap");
+	      
+	      while (curaddr>addr)
+		{
+		  curaddr-=64*1024*1024;
+		  munmap(curaddr,64*1024*1024);
+		}
+	      
+	      return NULL;
+	    }
+
+	  DPRINTF(0, (stderr, " %x", resaddr));
+	  
+	  curaddr+=curlen;
+	  len-=curlen;
+	}
+      
+      DPRINTF(0, (stderr, "\n"));
+    }
+  else
+    {
+      addr = mmap(0, len, OS_VM_PROT_ALL, flags, -1, 0);
+
+      if (addr == (os_vm_address_t) -1)
+	{
+	  perror("mmap");
+	  return NULL;
+	}
+      
+      DPRINTF(0, (stderr, " %x\n", addr));
+    }
+
+  return addr;
+}
+
+void os_invalidate(os_vm_address_t addr, os_vm_size_t len)
+{
+  DPRINTF(0, (stderr, "os_invalidate %x %d\n", addr, len));
+
+  if (munmap(addr, len) == -1)
+    perror("munmap");
+}
+
+os_vm_address_t os_map(int fd, int offset, os_vm_address_t addr,
+		       os_vm_size_t len)
+{
+  addr = mmap(addr, len,
+	      OS_VM_PROT_ALL,
+	      MAP_PRIVATE | MAP_FILE | MAP_FIXED,
+	      fd, (off_t) offset);
+
+  if (addr == (os_vm_address_t) -1)
+    perror("mmap");
+
+  return addr;
+}
+
+void os_flush_icache(os_vm_address_t address, os_vm_size_t length)
+{
+}
+
+void os_protect(os_vm_address_t address, os_vm_size_t length,
+		os_vm_prot_t prot)
+{
+  if (mprotect(address, length, prot) == -1)
+    perror("mprotect");
+}
+
+
+
+static boolean in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
+{
+  char* beg = (char*) sbeg;
+  char* end = (char*) sbeg + slen;
+  char* adr = (char*) a;
+  return (adr >= beg && adr < end);
+}
+
+boolean valid_addr(os_vm_address_t addr)
+{
+  int ret;
+  os_vm_address_t newaddr;
+  newaddr = os_trunc_to_page(addr);
+
+  if (   in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE)
+      || in_range_p(addr, STATIC_SPACE_START   , STATIC_SPACE_SIZE   )
+      || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size  )
+      || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size  )
+      || in_range_p(addr, CONTROL_STACK_START  , CONTROL_STACK_SIZE  )
+      || in_range_p(addr, BINDING_STACK_START  , BINDING_STACK_SIZE  ))
+    return TRUE;
+  return FALSE;
+}
+
+
+static void sigsegv_handler(HANDLER_ARGS)
+{
+
+  /*
+   * Since NetBSD on x86 currently provides no way to get the faulting
+   * memory address (i.e. the contents of the CR2 register), the page
+   * protection mechanism of the generational GC currently can't be
+   * used (see gengc.c), hence we don't neet to do anything here.
+   *
+   * See OpenBSD-os.c for details of what should be here, once NetBSD
+   * provides siginfo_t.
+   */
+
+  SAVE_CONTEXT();
+
+  DPRINTF(0, (stderr, "sigsegv:\n"));
+  interrupt_handle_now(signal, code, context);
+}
+
+static void sigbus_handler(HANDLER_ARGS)
+{
+  SAVE_CONTEXT();
+
+  DPRINTF(0, (stderr, "sigbus:\n"));
+  interrupt_handle_now(signal, code, context);
+}
+
+void os_install_interrupt_handlers(void)
+{
+  interrupt_install_low_level_handler(SIGSEGV, sigsegv_handler);
+  interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
+}
diff --git a/lisp/gencgc.c b/lisp/gencgc.c
index 3e03314c8..14bfb5913 100644
--- a/lisp/gencgc.c
+++ b/lisp/gencgc.c
@@ -7,7 +7,7 @@
  *
  * Douglas Crosher, 1996, 1997, 1998, 1999.
  *
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.25 2001/12/06 19:15:44 pmai Exp $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.26 2002/01/28 20:19:39 pmai Exp $
  *
  */
 
@@ -53,7 +53,13 @@ unsigned gencgc_verbose = 0;
  * To enable the use of page protection to help avoid the scavenging
  * of pages that don't have pointers to younger generations.
  */
+#ifdef __NetBSD__
+/* NetBSD on x86 has no way to retrieve the faulting address in the
+ * SIGSEGV handler, so for the moment we can't use page protection. */
+boolean  enable_page_protection = FALSE;
+#else
 boolean  enable_page_protection = TRUE;
+#endif
 
 /*
  * Hunt for pointers to old-space, when GCing generations >= verify_gen.
@@ -85,9 +91,10 @@ boolean check_code_fixups = FALSE;
 
 /*
  * To enable unmapping of a page and re-mmaping it to have it zero filled.
- * Note: this can waste a lot of swap on FreeBSD and OpenBSD(?) so don't unmap.
+ * Note: this can waste a lot of swap on FreeBSD and Open/NetBSD(?) so
+ * don't unmap.
  */
-#if defined(__FreeBSD__) || defined(__OpenBSD__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
 boolean gencgc_unmap_zero = FALSE;
 #else
 boolean gencgc_unmap_zero = TRUE;
-- 
GitLab