Initial revision
authorGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Wed, 8 Aug 1990 20:21:12 +0000 (20:21 +0000)
committerGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Wed, 8 Aug 1990 20:21:12 +0000 (20:21 +0000)
v7/src/microcode/hppacach.c [new file with mode: 0644]
v7/src/microcode/hppacach.h [new file with mode: 0644]

diff --git a/v7/src/microcode/hppacach.c b/v7/src/microcode/hppacach.c
new file mode 100644 (file)
index 0000000..be24282
--- /dev/null
@@ -0,0 +1,604 @@
+/* -*-C-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/hppacach.c,v 1.1 1990/08/08 20:21:12 jinx Exp $
+
+Copyright (c) 1990 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. */
+
+#include <stdio.h>
+#include <math.h>
+
+#include <sys/stat.h>
+#include <memory.h>
+
+#include <nlist.h>
+
+#include "hppacache.h"
+
+#define true                   1
+#define false                  0
+#define boolean                        int
+
+#ifdef DEBUG
+
+#define DEBUGGING(stmt) stmt
+
+#else
+
+#define DEBUGGING(stmt)                                                        \
+do {                                                                   \
+}while (0)
+
+#endif
+\f
+/* File that contains the symbol table for the kernel */
+
+#define KERNEL_FILE            "/hp-ux"
+
+/* File where the kernel image lives */
+
+#define KERNEL_MEMORY_FILE     "/dev/kmem"
+
+#define UTSNAME_SYMBOL         "utsname"
+#define PDC_CACHE_SYMBOL       "cache_tlb_parms"
+
+/* File where cached locations (to avoid nlist search) live */
+
+#define LOCATIONS_CACHE_FILE   "/tmp/hppa.cache"
+
+/* Operating system name */
+
+#define SYSNAME                        "HP-UX"
+
+static struct utsname sysinfo;
+static char **the_argv;
+\f
+void
+io_error (format, fname)
+     char *format, *fname;
+{
+  char errmsg[MAXPATHLEN + 257];
+  char errstring[MAXPATHLEN + 257];
+
+  sprintf (&errmsg[0], format, fname);
+  sprintf (&errstring[0], "%s: %s", (the_argv[0]), (&errmsg[0]));
+  perror (&errstring[0]);
+  return;
+}
+
+void
+io_lose (format, fname)
+     char *format, *fname;
+{
+  io_error (format, fname);
+  exit (1);
+}
+
+struct kernel_locations
+{
+  long utsname_location;
+  long pdc_cache_location;
+};
+
+struct nlist nl[] =
+{
+  { UTSNAME_SYMBOL },
+  { PDC_CACHE_SYMBOL },
+  { 0 },
+};
+
+int
+read_nlist (kloc)
+     struct kernel_locations *kloc;
+{
+  DEBUGGING (printf ("reading nlist...\n"));
+
+  if ((nlist (KERNEL_FILE, nl)) != 0)
+  {
+    io_error ("nlist: failed on %s", KERNEL_FILE);
+    return (-1);
+  }
+
+  DEBUGGING (printf ("reading nlist done.\n"));
+
+  kloc->utsname_location = nl[0].n_value;
+  kloc->pdc_cache_location = nl[1].n_value;
+
+  DEBUGGING (printf ("utsname location = 0x%x\n", kloc->utsname_location));
+  DEBUGGING (printf ("pdc_cache location = 0x%x\n", kloc->pdc_cache_location));
+
+  return (0);
+}
+\f
+void
+read_model (pdc_cache)
+     struct pdc_cache_dump *pdc_cache;
+{
+  int fd, read_result;
+  static char filename[MAXPATHLEN + 1];
+
+  sprintf ((&filename[0]),
+          MODELS_FILENAME,
+          CACHE_FILENAME_PATH);
+  fprintf (stderr, "%s:\n", (the_argv[0]));
+  fprintf (stderr,
+          "\tReading cache information from the model-based database (%s).\n",
+          (&filename[0]));
+  fd = (open ((&filename[0]), O_RDONLY));
+  if (fd < 0)
+  {
+    io_lose ("read_model: open (%s) failed", (&filename[0]));
+  }
+
+  while (true)
+  {
+    read_result = (read (fd, ((char *) pdc_cache), (sizeof (struct pdc_cache_dump))));
+    if (read_result != (sizeof (struct pdc_cache_dump)))
+    {
+      break;
+    }
+    if ((strcmp (sysinfo.machine, pdc_cache->hardware)) == 0)
+    {
+      close (fd);
+      fprintf (stderr,
+              "\tFound information for model %s in %s.\n",
+              sysinfo.machine, (&filename[0]));
+      return;
+    }
+  }
+  close (fd);
+  fprintf (stderr,
+          "\tCould not find information for model %s in %s.\n",
+          sysinfo.machine, (&filename[0]));
+  exit (1);
+}
+\f
+void
+read_parameters (pdc_cache)
+     struct pdc_cache_dump *pdc_cache;
+{
+  int kmem;
+
+  struct kernel_locations kloc;
+  struct utsname kerninfo;
+
+  if ((read_nlist (&kloc)) < 0)
+  {
+    read_model (pdc_cache);
+    return;
+  }
+  kmem = (open (KERNEL_MEMORY_FILE, O_RDONLY));
+  if (kmem < 0)
+  {
+    io_error ("read_parameters: open (%s) failed", KERNEL_MEMORY_FILE);
+    read_model (pdc_cache);
+    return;
+  }
+  else
+  {
+    if ((lseek (kmem, kloc.utsname_location, 0)) < 0)
+    {
+      io_lose ("read_parameters: lseek (%s) failed", KERNEL_MEMORY_FILE);
+    }
+
+    if ((read (kmem, &kerninfo, (sizeof (kerninfo)))) !=
+       (sizeof (kerninfo)))
+    {
+      io_lose ("read_parameters: read (%s) failed", KERNEL_MEMORY_FILE);
+    }
+
+    if ((memcmp (&kerninfo, &sysinfo, (sizeof (sysinfo)))) != 0)
+    {
+      fprintf (stderr, "read_parameters: uname and %s in %s differ.\n",
+              kloc.utsname_location, KERNEL_MEMORY_FILE);
+    }
+
+    strncpy (pdc_cache->hardware, (kerninfo.machine),
+            (sizeof (kerninfo.machine)));
+
+    if ((lseek (kmem, (kloc.pdc_cache_location), 0)) < 0)
+    {
+      io_lose ("read_parameters: lseek (%s) failed", KERNEL_MEMORY_FILE);
+    }
+
+    if  ((read (kmem, pdc_cache->cache_format,
+               (sizeof (pdc_cache->cache_format)))) !=
+        (sizeof (pdc_cache->cache_format)))
+    {
+      io_lose ("read_parameters: read (%s) failed", KERNEL_MEMORY_FILE);
+    }
+
+    if ((close (kmem)) < 0)
+    {
+      io_lose ("read_parameters: close (%s) failed", KERNEL_MEMORY_FILE);
+    }
+  }
+  return;
+}
+\f
+void
+print_sel (sel, name, pattern, op)
+     unsigned int sel;
+     char *name;
+     char *pattern;
+     char *op;
+{
+  switch (sel)
+  {
+    case 0:
+      printf ("\n      Both ");
+      printf (pattern, "D");
+      printf (" and ");
+      printf (pattern, "I");
+      printf (" must be used to %s it.", op);
+      break;
+
+    case 1:
+      printf ("\n      Only ");
+      printf (pattern, "D");
+      printf (" needs to be used to %s it.", op);
+      break;
+
+    case 2:
+      printf ("\n      Only ");
+      printf (pattern, "I");
+      printf (" needs to be used to %s it.", op);
+      break;
+
+    case 3:
+      printf ("\n      Either ");
+      printf (pattern, "D");
+      printf (" or ");
+      printf (pattern, "I");
+      printf (" can be used to %s it.", op);
+      break;
+
+    default:
+      fprintf (stderr, "\n      Bad %s value %d.", name, (sel));
+      break;
+  }
+
+  return;
+}
+
+void
+print_cst (cst)
+     unsigned int cst;
+{
+  switch (cst)
+  {
+    case 0:
+      printf ("\n      It does not issue coherent operations.");
+      break;
+
+    case 1:
+      printf ("\n      It issues coherent operations.");
+      break;
+
+    default:
+      printf ("\n      It has a reserved cst value %d.", (cst));
+      break;
+  }
+  return;
+}
+\f
+void
+print_cache (info, name, write_only_p)
+     struct cache_info *info;
+     char *name;
+     boolean write_only_p;
+{
+  printf ("\n");
+
+  /* First print the user-readable information as a comment. */
+
+  printf ("    /*\n");
+  printf ("      %s-cache information:\n", name);
+
+  printf ("\tsize\t\t%ld bytes (%ld K).\n", info->size, (info->size / 1024));
+  printf ("\tconf\t\t0x%08lx\n", info->conf.word);
+  printf ("\tbase\t\t0x%lx\n", info->base);
+  printf ("\tstride\t\t%ld bytes.\n", info->stride);
+  printf ("\tcount\t\t%ld entries.\n", info->count);
+  printf ("\tloop\t\t%ld association%s per entry.\n",
+         info->loop, ((info->loop == 1) ? "" : "s"));
+
+  printf ("\tblock size\t%d line%s.\n",
+         info->conf.bits.block,
+         ((info->conf.bits.block == 1) ? "" : "s"));
+  printf ("\tline size\t%d (16-byte units).\n", info->conf.bits.line);
+
+  if (write_only_p)
+  {
+    printf ("      It is a read-only cache.");
+  }
+  else if (info->conf.bits.wt == 0)
+  {
+    printf ("      It is a write-to cache.");
+  }
+  else
+  {
+    printf ("      It is a write-through cache.");
+  }
+
+  print_cst ((info->conf.bits.cst));
+  print_sel ((info->conf.bits.fsel), "f-sel", "F%sC", "flush");
+
+  /* Now print the C-readable information. */
+
+  printf ("\n    */\n");
+  printf ("    { %ld, 0x%08lx, 0x%lx, %ld, %ld, %ld }",
+         info->size, info->conf.word, info->base,
+         info->stride, info->count, info->loop);
+
+  return;
+}
+\f
+void
+print_tlb (info, name)
+     struct tlb_info *info;
+     char *name;
+{
+  printf ("\n");
+
+  /* First print the user-readable information as a comment. */
+
+  printf ("    /*\n");
+  printf ("      %s-TLB information:\n", name);
+
+  printf ("\tsize\t\t%ld bytes (%ld K).\n",
+         info->size, (info->size / 1024));
+  printf ("\tconf\t\t0x%08lx.\n", info->conf.word);
+  printf ("\tsp_base\t\t0x%lx.\n", info->sp_base);
+  printf ("\tsp_stride\t%ld.\n", info->sp_stride);
+  printf ("\tsp_count\t%ld.\n", info->sp_count);
+  printf ("\toff_base\t0x%lx.\n", info->off_base);
+  printf ("\toff_stride\t%ld.\n", info->off_stride);
+  printf ("\toff_count\t%ld.\n", info->off_count);
+  printf ("\tloop\t\t%ld association%s per entry.",
+         info->loop, ((info->loop == 1) ? "" : "s"));
+  
+  print_cst ((info->conf.bits.cst));
+  print_sel ((info->conf.bits.psel), "p-sel", "P%sTLB", "purge");
+
+  /* Now print the C-readable information. */
+
+  printf ("\n    */\n");
+  printf ("    { %ld, 0x%08lx, 0x%lx, %ld, %ld, 0x%lx, %ld, %ld, %ld }",
+         info->size, info->conf.word,
+         info->sp_base, info->sp_stride, info->sp_count,
+         info->off_base, info->off_stride, info->off_count,
+         info->loop);
+
+  return;  
+}
+
+void
+print_parameters (pdc_cache)
+     struct pdc_cache_dump *pdc_cache;
+{
+  struct pdc_cache_result *io_arch_format;
+
+  printf ("/* Emacs: Use -*- C -*- mode when editting this file. */\n\n");
+  printf ("{\n  /* Cache description for %s, an HP PA %s processor. */\n\n",
+         sysinfo.nodename,
+         sysinfo.machine);
+
+  io_arch_format = ((struct pdc_cache_result *) &(pdc_cache->cache_format));
+
+  printf ("  \"%s\",\n\n  {", pdc_cache->hardware);
+
+  print_cache (&(io_arch_format->I_info), "I", true);
+  printf (",");
+  print_cache (&(io_arch_format->D_info), "D", false);
+  printf (",");
+
+  print_tlb (&(io_arch_format->IT_info), "I");
+  printf (",");
+  print_tlb (&(io_arch_format->DT_info), "D");
+  printf ("\n");
+
+  printf ("  }};\n");
+  return;
+}
+\f
+static char dumpname[MAXPATHLEN + 1];
+
+void
+dump_parameters (pdc_cache)
+     struct pdc_cache_dump *pdc_cache;
+{
+  int file;
+
+  sprintf (&dumpname[0],
+          CACHE_FILENAME,
+          CACHE_FILENAME_PATH,
+          sysinfo.nodename,
+          sysinfo.machine);
+
+  file = open (&dumpname[0], (O_WRONLY | O_CREAT | O_TRUNC), 0664);
+  if (file < 0)
+  {
+    io_lose ("dump_parameters: open (%s) failed", dumpname);
+  }
+  if ((write (file, pdc_cache, (sizeof (struct pdc_cache_dump)))) !=
+      (sizeof (struct pdc_cache_dump)))
+  {
+    io_lose ("dump_parameters: write (%s) failed", dumpname);
+  }
+  if ((close (file)) != 0)
+  {
+    io_lose ("dump_parameters: close (%s) failed", dumpname);
+  }
+  return;
+}
+
+void
+read_stored_parameters (old_pdc_cache)
+     struct pdc_cache_dump *old_pdc_cache;
+{
+  int file;
+
+  sprintf (&dumpname[0],
+          CACHE_FILENAME,
+          CACHE_FILENAME_PATH,
+          sysinfo.nodename,
+          sysinfo.machine);
+
+  file = open (&dumpname[0], (O_RDONLY), 0);
+  if (file < 0)
+  {
+    io_lose ("read_stored_parameters: open (%s) failed", dumpname);
+  }
+  if ((read (file, old_pdc_cache, (sizeof (struct pdc_cache_dump)))) !=
+      (sizeof (struct pdc_cache_dump)))
+  {
+    io_lose ("read_stored_parameters: read (%s) failed", dumpname);
+  }
+  if ((close (file)) != 0)
+  {
+    io_lose ("read_stored_parameters: close (%s) failed", dumpname);
+  }
+  return;
+}
+
+void
+verify_parameters (new_pdc_cache, old_pdc_cache)
+     struct pdc_cache_dump *new_pdc_cache, *old_pdc_cache;
+{
+  boolean lose;
+
+  lose = false;
+  if ((strcmp (new_pdc_cache->hardware, old_pdc_cache->hardware)) != 0)
+  {
+    lose = true;
+    printf ("Model differs: old = %s; current = %s.\n",
+           new_pdc_cache->hardware, old_pdc_cache->hardware);
+  }
+  if ((memcmp (&new_pdc_cache->cache_format,
+              &old_pdc_cache->cache_format,
+              (sizeof (struct pdc_cache_result)))) != 0)
+  {
+    lose = true;
+    printf ("The stored cache information is incorrect.\n");
+  }
+  if (!lose)
+  {
+    printf ("The stored cache information is correct.\n");
+  }
+  return;
+}
+\f
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int
+    count,
+    uname_result;
+  struct pdc_cache_dump
+    new_pdc_cache_s, old_pdc_cache_s,
+    *new_pdc_cache, *old_pdc_cache;
+
+  the_argv = argv;
+  new_pdc_cache = ((struct pdc_cache_dump *) NULL);
+  old_pdc_cache = ((struct pdc_cache_dump *) NULL);
+
+  uname_result = (uname (&sysinfo));
+  if (uname_result < 0)
+  {
+    fprintf (stderr, "%s: uname failed.\n", argv[0]);
+    exit (1);
+  }
+
+  if (argc <= 1)
+  {
+    if (new_pdc_cache == ((struct pdc_cache_dump *) NULL))
+    {
+      read_parameters (&new_pdc_cache_s);
+      new_pdc_cache = &new_pdc_cache_s;
+    }
+    dump_parameters (new_pdc_cache);
+  }
+  else
+  {
+    for (count = 1; count < argc; count++)
+    {
+      if ((strcmp ((argv[count]), "-printnew")) == 0)
+      {
+       if (new_pdc_cache == ((struct pdc_cache_dump *) NULL))
+       {
+         read_parameters (&new_pdc_cache_s);
+         new_pdc_cache = &new_pdc_cache_s;
+       }
+       print_parameters (new_pdc_cache);
+      }
+      else if ((strcmp ((argv[count]), "-printold")) == 0)
+      {
+       if (old_pdc_cache == ((struct pdc_cache_dump *) NULL))
+       {
+         read_stored_parameters (&old_pdc_cache_s);
+         old_pdc_cache = &old_pdc_cache_s;
+       }
+       print_parameters (old_pdc_cache);
+      }
+      else if ((strcmp ((argv[count]), "-dump")) == 0)
+      {
+       if (new_pdc_cache == ((struct pdc_cache_dump *) NULL))
+       {
+         read_parameters (&new_pdc_cache_s);
+         new_pdc_cache = &new_pdc_cache_s;
+       }
+       dump_parameters (new_pdc_cache);
+      }
+      else if ((strcmp ((argv[count]), "-verify")) == 0)
+      {
+       if (new_pdc_cache == ((struct pdc_cache_dump *) NULL))
+       {
+         read_parameters (&new_pdc_cache_s);
+         new_pdc_cache = &new_pdc_cache_s;
+       }
+       if (old_pdc_cache == ((struct pdc_cache_dump *) NULL))
+       {
+         read_stored_parameters (&old_pdc_cache_s);
+         old_pdc_cache = &old_pdc_cache_s;
+       }
+       verify_parameters (new_pdc_cache, old_pdc_cache);
+      }
+      else
+      {
+       fprintf (stderr, "usage: %s [-dump] [-verify] [-printnew] [-printold]\n",
+                argv[0]);
+       exit (1);
+      }
+    }
+  }
+  exit (0);
+}
diff --git a/v7/src/microcode/hppacach.h b/v7/src/microcode/hppacach.h
new file mode 100644 (file)
index 0000000..0b34f61
--- /dev/null
@@ -0,0 +1,160 @@
+/* -*-C-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/hppacach.h,v 1.1 1990/08/08 20:20:56 jinx Exp $
+
+Copyright (c) 1990 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. */
+
+#ifndef HPPACACHE_H            /* Prevent multiple inclusion */
+
+#define HPPACACHE_H
+
+#ifdef C_SCHEME
+#include "paths.h"
+#define CACHE_FILENAME_PATH SCHEME_SOURCES_PATH
+#define MODELS_FILENAME "HPPAmodels"
+#endif
+
+/*
+   Format strings used to determine the name of the file
+   where to store (and examine) the cache description.
+
+   The strings are used as in
+   printf (CACHE_FILENAME, CACHE_FILENAME_PATH, hostname_string, model_string);
+
+   The default value (below) would generate the file name
+   /tmp/altdorf.cache
+   when running on a machine named altdorf.
+
+   To ignore a string parameter, use the %.0s format.
+ */
+
+#ifndef CACHE_FILENAME_PATH
+#define CACHE_FILENAME_PATH "/tmp/"
+#endif
+
+#ifndef CACHE_FILENAME
+#define CACHE_FILENAME "%s%s.cache"
+#endif /* CACHE_FILENAME */
+
+#ifndef MODELS_FILENAME
+#define MODELS_FILENAME "%shppamodels"
+#endif
+\f
+#define I_CACHE                1
+#define D_CACHE                2
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <machine/cpu.h>
+#include <machine/pdc_rqsts.h>
+#include <fcntl.h>
+
+/* PDC_CACHE (processor dependent code cache information call)
+   return data destructuring.
+
+   This is the same information as in machine/pdc_rqsts.h
+   pdc_cache_rtn_block, but with fields as defined in the PDC_CACHE
+   section of the I/O Architecture Manual.
+
+   The main difference is the cache configuration field.
+   Which is correct?
+ */
+
+union cache_conf
+{
+  unsigned long word;
+  struct
+  {
+    unsigned block:    8;
+    unsigned line:     3;
+    unsigned res1:     2;
+    unsigned wt:       1;
+    unsigned fsel:     2;
+    unsigned cst:      3;
+    unsigned res2:     11;
+    unsigned hv:       2;
+  } bits;
+};
+
+struct cache_info
+{
+  unsigned long size;          /* in bytes */
+  union cache_conf conf;       /* format description */
+  unsigned long base;          /* start address */
+  unsigned long stride;                /* in bytes */
+  unsigned long count;         /* number of entries */
+  unsigned long loop;          /* set associativity */
+};
+
+union tlb_conf
+{
+  unsigned long word;
+  struct
+  {
+    unsigned res1:     12;
+    unsigned psel:     2;
+    unsigned hv1:      1;
+    unsigned res2:     1;
+    unsigned cst:      3;
+    unsigned res3:     11;
+    unsigned hv2:      2;
+  } bits;
+};
+
+struct tlb_info
+{
+  unsigned long size;          /* number of entries */
+  union tlb_conf conf;         /* format description */
+  unsigned long sp_base;       /* space parameters */
+  unsigned long sp_stride;
+  unsigned long sp_count;
+  unsigned long off_base;      /* offset parameters */
+  unsigned long off_stride;
+  unsigned long off_count;
+  unsigned long loop;          /* set associativity */
+};
+
+struct pdc_cache_result
+{
+  struct cache_info I_info;
+  struct cache_info D_info;
+  struct tlb_info IT_info;
+  struct tlb_info DT_info;
+};
+
+struct pdc_cache_dump
+{
+  char hardware[sizeof (utsname.machine)];
+  struct pdc_cache_rtn_block cache_format;
+};
+
+#endif /* HPPACACHE_H */